File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+ import sys
2+
3+ read = lambda : sys .stdin .readline ().rstrip ()
4+
5+
6+ class Problem :
7+ def __init__ (self ):
8+ self .t , self .p = read (), read ()
9+ self .n , self .m = len (self .t ), len (self .p )
10+
11+ def solve (self ) -> None :
12+ result = self .kmp_search (self .get_prefix_table ())
13+
14+ print (len (result ))
15+ print (" " .join (map (str , result )))
16+
17+ def get_prefix_table (self ) -> list [int ]:
18+ prefix_table , y = [0 ] * self .m , 0
19+
20+ for x in range (1 , self .m ):
21+ while y > 0 and self .p [x ] != self .p [y ]:
22+ y = prefix_table [y - 1 ]
23+
24+ if self .p [x ] == self .p [y ]:
25+ y += 1
26+ prefix_table [x ] = y
27+
28+ return prefix_table
29+
30+ def kmp_search (self , prefix_table : list [int ]) -> list [int ]:
31+ result , y = [], 0
32+
33+ for x in range (self .n ):
34+ while y > 0 and self .t [x ] != self .p [y ]:
35+ y = prefix_table [y - 1 ]
36+
37+ if self .t [x ] == self .p [y ]:
38+ y += 1
39+
40+ if y == self .m :
41+ result .append (x - self .m + 2 )
42+ y = prefix_table [y - 1 ]
43+
44+ return result
45+
46+
47+ if __name__ == "__main__" :
48+ Problem ().solve ()
Original file line number Diff line number Diff line change 1+ [
2+ {
3+ "input" : [
4+ " ABC ABCDAB ABCDABCDABDE" ,
5+ " ABCDABD"
6+ ],
7+ "expected" : [
8+ " 1" ,
9+ " 16"
10+ ]
11+ }
12+ ]
Original file line number Diff line number Diff line change 1+ import json
2+ import os .path
3+ import unittest
4+ from io import StringIO
5+ from unittest .mock import patch
6+
7+ from parameterized import parameterized
8+
9+ from main import Problem
10+
11+
12+ def load_sample (filename : str ):
13+ path = os .path .join (os .path .dirname (os .path .abspath (__file__ )), filename )
14+
15+ with open (path , "r" ) as file :
16+ return [(case ["input" ], case ["expected" ]) for case in json .load (file )]
17+
18+
19+ class TestCase (unittest .TestCase ):
20+ @parameterized .expand (load_sample ("sample.json" ))
21+ def test_case (self , case : str , expected : list [str ]):
22+ # When
23+ with (
24+ patch ("sys.stdin.readline" , side_effect = case ),
25+ patch ("sys.stdout" , new_callable = StringIO ) as output ,
26+ ):
27+ Problem ().solve ()
28+
29+ result = output .getvalue ().rstrip ()
30+
31+ # Then
32+ self .assertEqual ("\n " .join (expected ), result )
33+
34+
35+ if __name__ == "__main__" :
36+ unittest .main ()
You can’t perform that action at this time.
0 commit comments