您的位置:首页 > 其它

KMP(SOJ3596)

2014-03-21 21:16 113 查看
(2012-07-15 19:28:27)

SOJ3596: http://cstest.scu.edu.cn/soj/problem.action?id=3596
这道题采用的算法是DP+KMP,也是我做KMP的题中最具挑战性的一道。

首先利用KMP算法将所有的word在text中的所有位置(包括起点和终点)存到一个struct数组中。

至于DP,设xiaoye[i]表示以text[i]为结尾的结果,则求xiaoye[i]即是对所有的满足:j<i,xiaoye[j]>0,并且从字符text[j+1]到字符text[i]是某一个word条件的xiaoye[j]作xiaoye[i]=xiaoye[i]+xiaoye[j]的处理。但是直接按照这个思路处理会超时,倒过来进行就会大大提高效率。

这需要对struct数组进行预处理,也就是下面的cmp函数。

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int next[1005];
char text[1000005];
int sum;
struct node
{
char pattern[1005];
}word[1005];
struct Node
{
int a;
int b;
}position[1000005];
void get_next(char *pattern)
{
int j=0;
int k=-1;
next[0]=-1;
while(pattern[j])
{
if(k==-1 || pattern[j]==pattern[k])
{
++j;
++k;
if(pattern[j]!=pattern[k])
next[j]=k;
else
next[j]=next[k];
}
else
k=next[k];
}
}
void KMP(char *pattern)
{
int i=0;
int j=0;
int result=0;
int lP=strlen(pattern);
while(text[i])
{
if(text[i]==pattern[j])
{
i++;
j++;
}
else if(next[j]==-1)
{
j=0;
i++;
}
else
j=next[j];
if(j==lP-1)
{
position[sum].a=i-lP+1;
position[sum++].b=i-1;
j=next[j];//这里的next[j]即是next['0']的值,显然只能>=0.

}
}
}
int cmp(Node x,Node y)
{
return x.a<y.a || (x.a==y.a && x.b<y.b);
}
int xiaoye[1000005];
int main()
{
int test;
int n;
int i;
scanf("%d",&test);
while(test--)
{
sum=0;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%s",word[i].pattern);
strcat(word[i].pattern,"0");
}
scanf("%s",text);
for(i=0;i<n;i++)
{
get_next(word[i].pattern);
KMP(word[i].pattern);
}
int lT=strlen(text);
memset(xiaoye,0,sizeof(xiaoye));
sort(position,position+sum,cmp);
for(i=0;i<sum;i++)
{
if(position[i].a==0)
xiaoye[position[i].b]++;
else
{
xiaoye[position[i].b]=(xiaoye[position[i].b]+xiaoye[position[i].a-1])%835672545;
}
}
printf("%d\n",xiaoye[lT-1]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: