codevs3160 两个串的最长公共子串 后缀自动机

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zy704599894/article/details/82832605

题目描述 Description

给出两个由小写字母组成的字符串,求它们的最长公共子串的长度。

输入描述 Input Description

读入两个字符串

输出描述 Output Description

输出最长公共子串的长度

样例输入 Sample Input

yeshowmuchiloveyoumydearmotherreallyicannotbelieveit
yeaphowmuchiloveyoumydearmother

样例输出 Sample Output

27

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxm = 100005;
struct node
{
	int link, len;
	int Next[26];
}st[maxm*3];
int cnt, last;
char str[maxm];
void init()
{
	memset(st, 0, sizeof(st));
	st[0].link = -1;
	st[0].len = 0;
	cnt = last = 0, cnt++;
}
void insert(int c)
{
	int p=last, now = cnt++, rev;
	st[now].len = st[p].len + 1;
	while (p != -1 && !st[p].Next[c])
		st[p].Next[c] = now, p = st[p].link;
	if (p == -1) st[now].link = 0;
	else
	{
		int q = st[p].Next[c];
		if (st[q].len == st[p].len + 1)
			st[now].link = q;
		else
		{
			rev = cnt++;
			st[rev] = st[q];
			st[rev].len = st[p].len + 1;
			while (p != -1 && st[p].Next[c] == q)
				st[p].Next[c] = rev, p = st[p].link;
			st[q].link = st[now].link = rev;
		}
	}
	last = now;
}
int find()
{
	int i, now, len, ans, p;
	now = ans = 0;
	p = last;
	len = strlen(str);
	for (i = 0;i < len;i++)
	{
		int id = str[i] - 'a';
		if (st[p].Next[id])
			p = st[p].Next[id], now++;
		else
		{
			while (p != -1 && !st[p].Next[id])
				p = st[p].link;
			if (p == -1) p = 0, now = 0;
			else now = st[p].len + 1, p = st[p].Next[id];
		}
		ans = max(ans, now);
	}
	return ans;
}
int main()
{
	int n, i, j, k, sum;
	init();
	scanf("%s", str);
	for (i = 0;str[i] != '\0';i++)
		insert(str[i] - 'a');
	scanf("%s", str);
	printf("%d\n", find());
}

猜你喜欢

转载自blog.csdn.net/zy704599894/article/details/82832605