串串乱记(长期

这里贴板子, 近一周每天都要打截止那天早上已经会的。

知识笔记贴在:

note 1

理解后缀排序

LCP部分性质/证明 与后缀数组的 rk 数组与 height 数组


KMP模板

#include<bits/stdc++.h>

using namespace std;

const int N = 1e6 + 233;

char s1[N], s2[N];
int l_1, l_2;
int fil[N];

int main()
{
	scanf("%s%s",s1+1,s2+1);
	l_1 = strlen(s1+1), l_2 = strlen(s2+1);
	fil[1]=0;
	for(int i=2,j=0; i<=l_2; ++i) {
		while(j && s2[j+1]!=s2[i]) j=fil[j];
		if(s2[j+1] == s2[i]) ++j;
		fil[i] = j;
	}
	for(int i=1,j=0; i<=l_1; ++i) {
		while(j && (j==l_2 || s2[j+1]!=s1[i])) j=fil[j];
		if(s2[j+1] == s1[i]) ++j;
		if(j==l_2) cout << (i-l_2+1) << '
';
	}
	for(int i=1; i<=l_2; ++i) cout << fil[i] << ' ';
	return 0;
}

AC 自动机板子

struct acam{
	int tr[N][26], fil[N], fa[N], tot;
	void ins(char *s, int n)
	{
		int x=0;
		for(int i=0 i<n; ++i) {
			char  ch = s[i] - 'a';
			if(!tr[x][ch]) {
				int y = ++tot;
				tr[x][ch] = y;
				fa[y] = x;
			}
			x = tr[x][ch];
		}
	}
	void get_fail()
	{
		queue<int>q;
		for(int i=0; i<26; ++i)
			if(tr[0][i]) q.push(tr[0][i]), fil[tr[0][i]] = 0;
		while(!q.empty())
		{
			int x = q.front(); q.pop();
			for(int i=0; i<26; ++i)
				if(tr[x][i]) fil[tr[x][i]] = tr[fil[x]][i], q.push(tr[x][i]);
				else tr[x][i] = tr[fil[x]][i];
		}
	}
} A;

倍增后缀排序

//nlogn倍增后缀排序
char s[MAXN];

int c[MAXN];
int x[MAXN];
int y[MAXN];
int sa[MAXN];

inline void get_sa(int n, int m) {
	for(int i = 1; i <= n; ++i) ++c[x[i] = s[i]];
	for(int i = 1; i <= m; ++i) c[i] += c[i-1];
	for(int i = n; i >= 1; --i) sa[c[x[i]]--] = i;
	for(int w = 1, q = 0; w < n; w <<= 1, q = 0) {
		for(int i = n-k+1; i <= n; ++i) y[++q] = i;
		for(int i = 1; i <= n; ++i) if(sa[i] > k) y[++q] = sa[i] - k;
		for(int i = 1; i <= m; ++i) c[i] = 0;
		for(int i = 1; i <= n; ++i) c[x[i]]++;
		for(int i = 1; i <= m; ++i) c[i] += c[i-1];
		for(int i = n; i >= 1; --i) sa[c[x[y[i]]]--] = y[i];
		swap(x, y); x[sa[1]] = q = 1;
		for(int i=2; i<=n; ++i)
			x[sa[i]] = y[sa[i]] == y[sa[i-1]] && y[sa[i] + w] == y[sa[i-1] + w] ? q : ++q;
		if(q == n) break;
		m = q;
	}
}

rk + height 数组

int rk[N], height[N];
inline void get_height() {
	for(int i=1; i<=n; ++i) rk[sa[i]] = i;
	for(int i=1, j, k=0; i<=n; ++i) {
		if(rk[i]==1) continue;
		j = sa[rk[i] - 1]; k -= k>0;
		while(i+k<=n && j+k<=n && s[i+k]==s[j+k]) ++k;
		height[rk[i]] = k;
	}
}
原文地址:https://www.cnblogs.com/tztqwq/p/14198850.html