题目:
http://lightoj.com/volume_showproblem.php?problem=1334题意:
给出一个母串和一个匹配串,求匹配串的所有的前后缀组合在母串中有多少个子串与之相同。前后缀长度不能超过len-1。
思路:
通过kmp加上一个dp[]递推数组求出母串中所有位置能够匹配匹配串的几个前缀,然后倒置求出能够匹配的后缀数,把所有相邻位置的前后缀匹配数相乘就是答案了。
代码:
//kopyh
#include <bits/stdc++.h>
#define N 1123456
using namespace std;
char s[N],ss[N];
int l[N],r[N],dp[N];
void getNext(char *pre, int len, int *next)
{
int i = 0,j = -1;
next[0] = -1;
dp[0]=1;
while(i < len)
{
if(j == -1 || pre[i] == pre[j])
{
next[++i] = ++j;
dp[i] = !j ? 1 : dp[j]+1;
}
else j = next[j];
}
}
void kmp(char *str, char *pre, int a[])
{
int lenp = strlen(pre), lens = strlen(str);
int next[lenp+1];
getNext(pre, lenp, next);
int i,j; i=j=0;
while(i < lens)
{
if(j == -1 || str[i] == pre[j])
{
i++;j++;
a[i] = j?dp[j]:0;
}
else j = next[j];
if(j==lenp)a[i]--;
}
}
int main()
{
int i,j,k,cas,T,t,x,y,z;
scanf("%d",&T);
cas=0;
while(T--)
{
scanf("%s%s",&s,&ss);
int n=strlen(s),m=strlen(ss);
kmp(s,ss,l);
reverse(s,s+n);
reverse(ss,ss+m);
kmp(s,ss,r);
long long res=0;
for(i=1;i<n;i++)
res+=(long long)l[i]*r[n-i];
printf("Case %d: %lld\n",++cas,res);
}
return 0;
}