hdu5769后缀自动机

此题用后缀自动机写也还是可以,只是有许多易错点

1.后缀自动机的节点复制后就和原数组的字符没有半点关系了,所以我们一定要注意使用amount这个变量,而不能通过maxx在原字符串中跟新值

2.在添加父亲指针时所有的amount都要减掉,这从后缀自动机的节点意义可以看出,每个节点代表的就是一些字符串集合

我们当然要把一些字符串集合拿出来给父亲咯。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
struct treee
{
	int son[26], maxx, faa, amount;
};
treee tree[250000];
int t;
char symbol[10];
char ss[100200];
int dis[100200];
int diantot = 1;
int now;
ll ans;
void insertt(char name, int pos)
{
	int temp = diantot++;
	tree[temp].maxx = pos;
	tree[temp].amount = dis[pos];
	int kind = name - 'a';
	while (now&&tree[now].son[kind] == 0)
	{
		tree[now].son[kind] = temp;
		now = tree[now].faa;
	}
	if (now == 0 && tree[now].son[kind] == 0)
	{
		tree[now].son[kind] = temp;
		tree[temp].faa = now;
	}
	else
	{
		int nextt = tree[now].son[kind];
		if (tree[nextt].maxx == (tree[now].maxx + 1))
		{
			tree[temp].faa = nextt;
			int poss = tree[temp].maxx - tree[nextt].maxx;
			tree[temp].amount = min(tree[temp].amount, poss);
		}
		else
		{
			int neww = diantot++;
			tree[neww] = tree[nextt];
			tree[neww].maxx = tree[now].maxx + 1;
			if (tree[nextt].amount == 0)
				tree[neww].amount = 0;
			else
			{
				int pos = min(tree[nextt].amount, tree[nextt].maxx - tree[neww].maxx);
				tree[neww].amount = tree[nextt].amount - pos;
				tree[nextt].amount = pos;
				pos = min(tree[temp].amount, tree[temp].maxx - tree[neww].maxx);
				tree[temp].amount = pos;
			}
			while (tree[now].son[kind] == nextt)
			{
				tree[now].son[kind] = neww;
				if (now == 0)
					break;
				now = tree[now].faa;
			}
			tree[nextt].faa = neww; tree[temp].faa = neww;
		}
	}
	now = temp;
}
int main()
{
	scanf("%d", &t);
	int k = 1;
	while (t--)
	{
		ans = 0;
		now = 0;
		diantot = 1;
		scanf("%s", symbol);
		scanf("%s", ss + 1);
		int len = strlen(ss + 1);
		for (int i = 1; i <= len; i++)
		{
			if (ss[i] == symbol[0])
				dis[i] = i;
			else
			{
				if (i - 1 >= 1)
					dis[i] = dis[i - 1];
				else
					dis[i] = 0;
			}
		}
		for (int i = 1; i <= len; i++)
		{
			insertt(ss[i], i);
		}
		for (int i = 1; i < diantot; i++)
			ans += tree[i].amount;
		printf("Case #%d: %lld\n", k++, ans);
		for (int i = 0; i < diantot; i++)
		{
			for (int j = 0; j < 26; j++)
				tree[i].son[j] = 0;
			tree[i].maxx = tree[i].faa = tree[i].amount = 0;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值