您的位置:首页 > 其它

模式匹配KMP POJ 3461

2014-05-17 23:53 295 查看
题目地址:http://poj.org/problem?id=3461

题目大意:在T串中找出W串出现的次数,T串的长度小于等于1000000,W串的长度小于等于10000。

解题思路:赤裸裸地KMP,可是最近果真总是作死的节奏,一直感觉我对地址下标、数字神马的比较敏感,今天卡了将近一个小时。。。

程序代码:

/*
算法时间复杂度:O(m+n),m、n分别为两个串的长度。
与传统算法的区别就是:每一趟匹配过程中出现字符比较不等时,
不需回溯主串中用来指示字符的i指针
而是利用已经得到的“部分匹配”的结果
将模式串向右滑动尽可能远的距离,再进行比较。
next[j]数组:表明当模式串中第j个字符与主串中第i个字符不匹配时,
在模式中需重新和该字符进行比较的字符的位置。

*/

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>

const int M = 1000010;

char w[M];
char t[M];
int next[M];

void Init(int w_len)
{
next[0] = -1;
int i = 0, j = -1;
while (i < w_len)
{
if (j == -1 || (w[i] == w[j]))
{
i++;
j++;
next[i] = j;
}
else j = next[j];
}

}

int Kmp(int w_len, int t_len)
{
int i = 0, j = 0;
int cnt = 0;
while (i < t_len)
{
if (j == -1 || (t[i] == w[j]))
{
i++;
j++;
}
else
{
j = next[j];
}

if (j >= w_len)
{
cnt++;
}
}
return cnt;

}
int main()
{
int ncase;
scanf("%d", &ncase);
for (int i = 0; i < ncase; i++)
{
scanf("%s %s", w, t);
int w_len = strlen(w);
int t_len = strlen(t);
Init(w_len);
int ans = Kmp(w_len, t_len);
printf("%d\n", ans);
}
return 0;
}


一点感悟:曾经要是好好静下心来学算法,不是盲目地刷题,该是多好~~    学习算法是件快乐的事情,加油!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  kmp