匹配字符串……
……
……
会写n*m吗,这个肯定都会owo,暴力思想
会用pos吗?你可以冒险一试……据说pos就是用kmp写的
可以优化到O(M+n)级别……今天在大神的帮助下,终于听懂了……
先对要去匹配的对象(也就是说这个字符串可能在另一个被匹配的字符串中出现多次)操作,完成记录数组……你可以随便叫一个,就叫kmp好了
我有一个字符串,它即将要被匹配
举个栗子: k a p k a
kmp数组的值 : 0 0 0 1 2
数组里存储的f[i]是匹配到i位时,前缀和后缀的最长公共子串,其实也就是记录了第一位的字母在当前情况下,你又在哪一位匹配过了,等一下就可以直接跳到那里去,不必再一位位枚举了
j:=0;
for i:=2 to len do
begin
while (j>0)and(s[j+1]<>s[i]) do
j:=kmp[j];
if s[j+1]=s[i] then inc(j);
kmp[i]:=j;
end;
字符串 k a p k a
i: 2 3 4 5
j: 0 0 0 1
s[i] 'a' 'p' 'k' 'a'
s[j+1] 'k' 'k' 'k' 'a
kmp的值 00000 00000 00010 00012
好了,已经完成了一步,接下来把代码复制一遍,修改一下
我们来找个不同:
j:=0;
for i:=1 to lena do
begin
while (j>0)and(s[j+1]<>z[i]) do j:=kmp[j];
if s[j+1]=z[i] then inc(j);
if j=lena then exit(i-len);
end;
其实过程是一样的,一个是自己和自己,一个是两串之间,你可以自己再模拟一下。
上种程序返回的是匹配的位置
那么下面一种
j:=0;
for i:=1 to len do
begin
while(j>0)and(s[i]<>z[j+1])do
j:=kmp[j];
if(s[i]=z[j+1])then j:=j+1
if j=len then
begin
inc(ans);
j:=kmp[j];
end;
end;
返回的是匹配次数,还有返回匹配长度的,你也可以照着码一下。你需要思考一下,匹配完后要进行什么操作?其实上面已经写了,如果只要匹配一次,可以跳出,匹配多次,你就需要当做失配,继续做下去……
大概就是这样OAO
接下来………
来讲讲回文串,这个其实只能考裸的回文串,也没什么深的含义
一般两种:一段字符的最大回文串………n logn……枚举点,向两边扩展owo,其实也是暴力思想,我不甚清楚为什么复杂度可以优化到log级别owo。
第二种,相似回文……ababa babab 可以当做一种回文串,实际也是把它们处理一下 都变成12121……就可以做了
然后,口胡一下o(n)的算法 manacher QAQ 其实不怎么会用到吧……随便口胡一下就可以继续去口胡LCM 了
据说有分治加kmp的做法……
uses math;
var id,mx,i,n,ans:longint;
s:string;
str:string;//:array[0..10000] of char;
p:array[0..10000] of longint;
procedure kp;
begin
mx:=0;
for i:= 1 to n do
begin //比较一下两个的区别?
if mx>i then p[i]:=min(p[id+id-i],p[id]+id-i)//如果之前回文串延5的位置超过了现在的位置,也就是现在的位置在最长回文串内。
else
p[i]:=1;//没有超过?自己匹配!
while str[i+p[i]]=str[i-p[i]] do
inc(p[i]);
if p[i]+i>mx then//重新记录
begin
mx:=p[i]+i;
id:=i;
end;
end;
end;
procedure init;//这里的作用是统一奇数长度的字符串和偶数长度的字符串
begin
str[0] := '$';
str[1] := '#';
for i:=1 to n do
begin
str[(i-1)*2+2] := s[i];
str[(i-1)*2+3] := '#';
end;
n:=n*2+2;
end;
begin
readln(s);
n:=length(s);
init;
kp;
ans:=0;
for i:=1 to n do
if( p[i]>ans) then ans:=p[i];
writeln(ans-1);
end.//估计还有点错误,等我和nlogn的拍过之后再修改吧
说起来非常惭愧,我现在还是打pascal的……csdn居然都没有pascal的选项了,欸……
具体的操作步骤?
baidu有些blog写的非常好,还是自己去观摩吧
ps:在kmp的内容部分,我犯了严重的错误,不知道有没有看出来,我把z和s弄反了,大家在noip时不要犯弄错i j,弄错全局变量和局部变量的错误啊