HOJ 6629 string matching(扩展KMP,裸题)

扩展KMP,裸题

本题要点:
1、题目依次输入的字符串 s1 , s2 , 以 s1 为母串, s2 为子串,运行扩展 KMP 算法,
得到 extend 数组, 题目的伪代码的大概意思,就是把所有的 extend[i] 全部加起来,
但是,有一个注意的地方,就是,当 extend[i], 所表示的范围,如果能触及到 母串
s1 字符串的末尾的话, ans 需要减 1;

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MaxN = 1e6 + 10;
char s1[MaxN], s2[MaxN];
int Next[MaxN], extend[MaxN];
int T;

//预处理next 数组
void getNext(char* str)
{
	int i = 0, j, po, len = strlen(str);
	Next[0] = len;	
	while(i + 1 < len && str[i] == str[i + 1])	// 计算 next[1]
		++i;
	Next[1] = i;
	po = 1;	//初始化 po位置
	for(int i = 2; i < len; ++i)
	{
		if(Next[i - po] + i < Next[po] + po)	//第一种情况
		{
			Next[i] = Next[i - po];
		}else{	//第二种情况,要继续匹配才能得到next[i]的值
			j = Next[po] + po - i;	
			if(j < 0)
				j = 0;	//如果i>po+next[po],则要从头开始匹配
			while(i + j < len && str[j] == str[j + i])
				++j;
			Next[i] = j;
			po = i;
		}
	}
}

//计算extend 数组
void exkmp(char* s1, char* s2)	// s2 是子串,s1是母串
{
	int i = 0, j, po, len = strlen(s1), l2 = strlen(s2);
	getNext(s2);
	while(i < l2 && i < len && s1[i] == s2[i])
		++i;
	extend[0] = i;
	po = 0;	//初始化po的位置
	for(i = 1; i < len; ++i)
	{
		if(Next[i - po] + i < extend[po] + po)
		{
			extend[i] = Next[i - po];
		}else{
			j = extend[po] + po - i;
			if(j < 0)
				j = 0;
			while(i + j < len && j < l2 && s1[j + i] == s2[j])
			{
				++j;
			}
			extend[i] = j;
			po = i;
		}
	}
}

int main()
{
	scanf("%d", &T);
	while(T--)
	{
		scanf("%s", s1);
		strcpy(s2, s1);
		exkmp(s2, s1);
		long long ans = 0;
		int len = strlen(s2);
		for(int i = 1; i < len; ++i)
		{
			ans += extend[i] + 1;
			if(extend[i] + i == len)
			{
				--ans;
			}
		}
		printf("%lld\n", ans);
	}
	return 0;
}

/*
3
_Happy_New_Year_
ywwyww
zjczzzjczjczzzjc
*/

/*
17
7
32
*/

猜你喜欢

转载自blog.csdn.net/qq_38232157/article/details/108436557
今日推荐