题目链接https://vjudge.net/problem/2638259/origin
String matching is a common type of problem in computer science. One string matching problem is as following:
Given a string [Math Processing Error]s[0…len−1], please calculate the length of the longest common prefix of [Math Processing Error]s[i…len−1] and [Math Processing Error]s[0…len−1] for each [Math Processing Error]i>0.
I believe everyone can do it by brute force.
The pseudo code of the brute force approach is as the following:
We are wondering, for any given string, what is the number of compare operations invoked if we use the above algorithm. Please tell us the answer before we attempt to run this algorithm.
Input
The first line contains an integer [Math Processing Error]T, denoting the number of test cases.
Each test case contains one string in a line consisting of printable ASCII characters except space.
-
[Math Processing Error]1≤T≤30
-
string length [Math Processing Error]≤106 for every string
Output
For each test, print an integer in one line indicating the number of compare operations invoked if we run the algorithm in the statement against the input string.
Sample Input
3
Happy_New_Year
ywwyww
zjczzzjczjczzzjc
Sample Output
17
7
32
题目大意,有一个字符串,i=0,j=1,k=0,S【i+k】和S【j+k】 比较,如果相同,k++,再次比较,直到S【i+k】和S【j+k】不相同,j++,再次进行比较,求最终字符串的比较次数。
扩展kmp的模板题
贴上代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1000010;
int nxt[maxn];
char s[maxn];
ll solve(char str[])
{
ll ans = 0;
int i=0,j,po,len=strlen(str);
nxt[0]=len;
while(str[i]==str[i+1] && i+1<len) i++; nxt[1]=i;
ans += nxt[1];
if(nxt[1] != len - 1) ans++;
po=1;
for(i=2;i<len;i++)
{
if(nxt[i-po]+i < nxt[po]+po)
nxt[i]=nxt[i-po];
else
{
j = nxt[po]+po-i;
if(j<0) j=0;
while(i+j<len && str[j]==str[j+i]) j++; nxt[i]=j;
po=i;
}
ans += nxt[i];
if(nxt[i] != len - i) ans++;
}
return ans;
}
int main()
{
//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
int t;
scanf("%d", &t);
while(t--)
{
scanf("%s",s);
printf("%lld\n", solve(s));
}
return 0;
}
EKMP,扩展kmp。
解决的问题:定义母串S和子串T,S的长度为n,T的长度为m,求母串S中每一个后缀与子串T的最长前缀总数。
也就是说,设有extend数组:extend[i]表示T与S[i,n-1]的最长公共前缀,要求出所有extendi。
(注意到,如果存在若干个extend[i]=m,则表示T在S中完全出现,且是在位置i出现,这就是标准的KMP问题,所以一般将它称为扩展KMP算法。)
找到一篇写的很好的博客,讲解EKMP比较完整,附上链接:https://www.jianshu.com/p/107e47994d49