试题编号: 201409-3
试题名称: 字符串匹配
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行。你的程序还需支持大小写敏感选项:当选项打开时,表示同一个字母的大写和小写看作不同的字符;当选项关闭时,表示同一个字母的大写和小写看作相同的字符。
输入格式
输入的第一行包含一个字符串S,由大小写英文字母组成。
第二行包含一个数字,表示大小写敏感的选项,当数字为0时表示大小写不敏感,当数字为1时表示大小写敏感。
第三行包含一个整数n,表示给出的文字的行数。
接下来n行,每行包含一个字符串,字符串由大小写英文字母组成,不含空格和其他字符。
输出格式
输出多行,每行包含一个字符串,按出现的顺序依次给出那些包含了字符串S的行。
样例输入
Hello
1
5
HelloWorld
HiHiHelloHiHi
GrepIsAGreatTool
HELLO
HELLOisNOTHello
样例输出
HelloWorld
HiHiHelloHiHi
HELLOisNOTHello
样例说明
在上面的样例中,第四个字符串虽然也是Hello,但是大小写不正确。如果将输入的第二行改为0,则第四个字符串应该输出。
评测用例规模与约定
1<=n<=100,每个字符串的长度不超过100。
#朴素算法
s=input().strip()
m=int(input())
n=int(input())
for i in range(n):
#枚举每一个字母,扫描每一个位置并且判断是否匹配
x=input().strip()
if m==1 :
if x.find(s)!=-1:
print(x)
else:
if x.upper().find(s.upper())!=-1:
print(x)


推广到Next[i+1],它对应P[0]~P[i]的后缀和前缀。
此时后缀的最后一个字符是P[i],与这个字符相对应,把前缀的j也往后移一个字符,j = Next[i]。判断两种情况:
(1)若P[i] = P[j],则新的交集等于“阴影w+ P[i]”,交集的长度Next[i+1] = Next[i]+1。

2)若P[i] ≠ P[j],说明后缀的“阴影w+P[i]”与前缀的“阴影w+P[j]”不匹配,只能缩小范围找新的交集。

下图合并了前缀和后缀,画出完整的子串P[0]~P[i],最后的字符P[i]和P[j]不等。


把前缀往后滑动,也就是通过减小j来缩小前缀的范围,直到找到一个匹配的P[i] = P[j]为止。
如何减小j?只能在w上继续找最大交集,这个新的最大交集是Next[j],所以更新j’ = Next[j]。
下图斜线阴影v是w上的最大交集,下一步判断:
若P[i] = P[j’],则Next[i+1]等于v的长度加1,即Next[j’]+1;
若P[i] ≠ P[j’],继续更新j’。

10. KMP算法代码如下!!!
N=1000005
Next = [0]*N
def getNext(p): #计算Next[1]~Next[plen]
for i in range(1,len(p)):
j = Next[i]; #j的后移:j指向前缀阴影w的后一个字符
while j>0 and p[i] != p[j]: #阴影的后一个字符不相同
j = Next[j] #更新j
if p[i]==p[j]: Next[i+1] = j+1
else: Next[i+1] = 0
def kmp(s,p):
ans = 0
j = 0
for i in range(0,len(s)): #S的i指针,它不回溯,用for循环一直往前走。
#匹配S和P的每个字符
while j>0 and s[i]!=p[j]: #失配了
j=Next[j] #j滑动到Next[j]位置
if s[i]==p[j]: #若s[i]==p[j],说明当前P的字符和S的字符匹配j++,
#同时回到13行i++
#下一步匹配s[i+1]和p[j+1]。
#当前位置的字符匹配,继续
j+=1
ans = max(ans,j)
if j == len(p): return ans #最长前缀就是p的长度,直接返回
return ans #返回p在s中出现的最长前缀
s=input()
t=input()
getNext(t)
print(kmp(s,t))
#KMP算法实现
def find(x):
j=0
for i in range(len(x)):
while j!=0 and s[j]!=x[i]:
j=p[j]
if s[j]==x[i]:
j=j+1
if j==len(s):
return 1
return -1
s=input().strip()
m=int(input())
n=int(input())
if m==0:
s=s.upper()
#计算kmp算法的next数组,这里我叫p
p=[0 for _ in range(len(s)+1)]
p[1]=0
j=0
for i in range(1,len(s)):
while j != 0 and s[j] != s[i]:
j = p[j]
if s[j] == s[i]:
j = j + 1
p[i]=j
for i in range(n):
x=input().strip()
#枚举每一个母串,一次扫描
if m==1:
if find(x)!=-1:
print(x)
else:
if find(x.upper())!=-1:
print(x)
程序员节快乐!!!
