求字符串中長度爲k的本質不同串的個數

如果僅僅求長度爲k,使用滾動hash即可。

 

下面是求一段長度的本質不同串的個數。

Names for Babies

 LightOJ - 1314 

https://vjudge.net/contest/32333#problem/F

問題:

求字符串中長度爲k的本質不同串的個數。

思路:

後綴自動機中每個節點包含着一段連續長度的子串,遍歷每個節點,記一個差分數組即可統計長度爲1~|S|的不同子串個數。

代碼:

LightOJ - 1314 AC代碼,原題統計長度p到q的本質不同子串的個數)

#include <bits/stdc++.h>
//#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;

#ifdef LOCAL
#define debug(x) cout << "[" __FUNCTION__ ": " #x " = " << (x) << "]\n"
#define TIME cout << "RuningTime: " << clock() << "ms\n", 0
#else
#define TIME 0
#endif
#define hash_ 998244353
#define Continue(x) { x; continue; }
#define Break(x) { x; break; }
const int mod = 1e9 + 7;
const int N = 1e4 + 10;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
#define gc p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
inline int read(){ static char buf[1000000], *p1 = buf, *p2 = buf; register int x = false; register char ch = gc; register bool sgn = false; while (ch != '-' && (ch < '0' || ch > '9')) ch = gc; if (ch == '-') sgn = true, ch = gc; while (ch >= '0'&& ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc; return sgn ? -x : x; }
ll fpow(ll a, int b, int mod) { ll res = 1; for (; b > 0; b >>= 1) { if (b & 1) res = res * a % mod; a = a * a % mod; } return res; }
int len[N << 1];
int lnk[N << 1];
int cnt[N << 1];
int nxt[N << 1][26];
int idx;
int last;
int tot;
int sub[N << 1];
char s[N];
int c[N];
void init()
{
	last = idx = 1;
	lnk[1] = len[1] = 0;
}
void clear()
{
	memset(c, 0, sizeof c);
	memset(len, 0, sizeof len);
	memset(lnk, 0, sizeof lnk);
	memset(cnt, 0, sizeof cnt);
	memset(nxt, 0, sizeof nxt);
}
void extend(int c)
{
	int x = ++idx;
	len[x] = len[last] + 1;
	sub[x] = 1;
	int p;
	for (p = last; p && !nxt[p][c]; p = lnk[p])
		nxt[p][c] = x;
	if (!p)
		lnk[x] = 1, cnt[1]++;
	else
	{
		int q = nxt[p][c];
		if (len[p] + 1 == len[q])
			lnk[x] = q, cnt[q]++;
		else
		{
			int nq = ++idx;
			len[nq] = len[p] + 1;
			lnk[nq] = lnk[q];
			memcpy(nxt[nq], nxt[q], sizeof nxt[q]);
			for (; p && nxt[p][c] == q; p = lnk[p])
				nxt[p][c] = nq;
			lnk[q] = lnk[x] = nq;
			cnt[nq] += 2;
		}
	}
	last = x;
}
void solve()
{
	for (int i = 2; i <= idx; i++)
	{
		c[len[lnk[i]] + 1]++;
		c[len[i] + 1]--;
	}
}
int main()
{
#ifdef LOCAL
	freopen("E:/input.txt", "r", stdin);
#endif
	int t;
	cin >> t;
	int kcase = 0;
	while (t--)
	{
		init();
		clear();
		scanf("%s", s);
		int len = strlen(s);
		for (int i = 0; i < len; i++)
			extend(s[i] - 'a');
		solve();
		int p, q;
		cin >> p >> q;
		int cnt = 0;
		for (int i = 1; i <= len; i++)
			c[i] += c[i - 1];
		for (int i = p; i <= q; i++)
			cnt += c[i];
		printf("Case %d: %d\n", ++kcase, cnt);
	}
	return TIME;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章