题目链接:
http://poj.org/problem?id=3461
题目大意:
求前一个字符串在第二个字符中出现的次数
解题思路:
根据求出的kmpNext数组对第二个字符串进行匹配
代码如下:
// POJ3461.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#pragma warning (disable:4996) //去freopen的警告
#define _CRT_SECURE_NO_DEPRECATE //去scanf报错
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
void perKMP(char *src, int len, int *rule);
int KMP(char *src, int src_len, char *dest, int dest_len);
char src[100008], dest[1000008];
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
int ans = 0;
scanf("%s%s", &src, &dest);
ans=KMP(src, strlen(src), dest, strlen(dest));
printf("%d\n", ans);
}
return 0;
}
void perKMP(char *src, int len, int *rule)
{
int i=0, j=-1;
rule[0] = -1;
while (i < len)//i是判断到的个数j是循环节重复的个数
{
//printf("i1:%d j1:%d ", i, j);
while (-1 != j && src[i] != src[j])//找到最近与上一次的src[i]相等的字符,如果没有-1
{
//printf("src[%d]=%c ", j, src[j]);
j = rule[j];
}
//printf("src[%d]=%c src[%d]=%c ", i, src[i], j, src[j]);
i++;
j++;
//printf("src[%d]=%c src[%d]=%c ", i, src[i], j, src[j]);
if (src[i] == src[j])//比较下一位的字符是否相等,如果相等就让他等于j的值
{
rule[i] = rule[j];
}
else//如果不相等就让他等于他前面循环的一样的个数
{
rule[i] = j;
}
printf("rule[%d]=%d\n", i, rule[i]);
}
}
int KMP(char *src, int src_len, char *dest, int dest_len)
{
int rule[100008];
int i=0, j=0;
int ans = 0;
perKMP(src, src_len, rule);
/*for (int i = 0; i < src_len; i++)
{
printf("rule[%d]=%d\n", i, rule[i]);
}*/
//printf("%d", dest_len);
while (i < dest_len)//i为判断到的位数j为循环个数
{
while (-1 != j && dest[i] != src[j])//找到最近与上一次的src[i]相等的字符,如果没有-1
{
j = rule[j];
}
i++;
j++;
//printf("rule[%d]=%d\n", j,rule[j]);
if (j >= src_len)
{
//printf("%d\n",i-src_len);//匹配的位置
ans++;
j = rule[j];
}
}
return ans;
}