POJ-3294 後綴數組+單調棧
鏈接:here
題意就是有個字符串,每個字符串長度不超過, 求最長的一些子串,他們的出現次數超過字符串個數的一半。
令,按題目要求知道這個字符串肯定是至少個連續的的。
維護一個棧,記錄棧裏面屬於不同編號的後綴的數量,一旦達到個,就求一下他們的,取。
然後移動左端點,直到不同編號的後綴數量小於。
還有就是當棧裏面大小爲時,也要移動左端點。
因爲表示的是和的,單調棧的時候加入第個貢獻和移除第個貢獻的時候會有一個麻煩。。。
索性就把板子裏的的意思改了下。。。
反正改改了好久好久,有一點點細節吧。。。
DC3
#pragma comment(linker, "/STACK:102400000,102400000")
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<map>
#include<iostream>
#include<assert.h>
#include <algorithm>
#define fi first
#define se second
#define endl '\n'
#define o2(x) (x)*(x)
#define BASE_MAX 62
#define mk make_pair
#define eb push_back
#define all(x) (x).begin(), (x).end()
#define clr(a,b) memset((a),(b),sizeof((a)))
#define iis std::ios::sync_with_stdio(false); cin.tie(0)
#define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end())
using namespace std;
#pragma optimize("-O3")
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, int> pLi;
inline LL read(){
LL x=0;int f=0;char ch=getchar();
while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x=f?-x:x;
}
inline void write(LL x) {
if(x==0){putchar('0'),putchar('\n');return;}
if(x < 0) {putchar('-');x=-x;}
static char s[23];int l = 0;
while(x!=0)s[l++]=x%10+48,x/=10;
while(l)putchar(s[--l]);
putchar('\n');
}
int lowbit(int x) {return x&(-x);}
template<class T> T big(const T& a1,const T& a2) { return a1>a2?a1:a2; }
//template<typename T, typename ...R> T big (const T& f,const R& ...r) { return big(f, big (r...)); }
template<class T> T sml(const T& a1,const T& a2) { return a1<a2?a1:a2; }
//template<typename T, typename ...R> T sml (const T& f,const R& ...r) { return sml(f, sml (r...)); }
#ifndef ONLINE_JUDGE
void debug_out() { cerr << '\n'; }
template<typename T, typename ...R> void debug_out (const T& f,const R& ...r) { cerr << f << " "; debug_out (r...); }
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
#endif
#define print(x) write(x);
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int HMOD[] = {1000000009, 1004535809};
const LL BASE[] = {1572872831, 1971536491};
const int mod = 1e9 + 6;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int MXN = 5e5 + 7;
const int N =3e5+5;
int sa[N * 3], height[N], Rank[N];;
int wa[N], wb[N], wv[N], c[N];
int dp[N][24];
int c0(int *r, int a, int b) {
return r[a] == r[b] && r[a + 1] == r[b + 1] && r[a + 2] == r[b + 2];
}
int c12(int k, int *r, int a, int b) {
if (k == 2) return r[a] < r[b] || r[a] == r[b] && c12(1, r, a + 1, b + 1);
else return r[a] < r[b] || r[a] == r[b] && wv[a + 1] < wv[b + 1];
}
void _sort(int *r, int *a, int *b, int n, int m) {
int i;
for (i = 0; i < n; i++) wv[i] = r[a[i]];
for (i = 0; i < m; i++) c[i] = 0;
for (i = 0; i < n; i++) c[wv[i]]++;
for (i = 1; i < m; i++) c[i] += c[i - 1];
for (i = n - 1; i >= 0; i--) b[--c[wv[i]]] = a[i];
return;
}
void dc3(int *r,int *sa,int n,int m) {
int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
r[n]=r[n+1]=0;
for(i=0; i<n; i++) if(i%3!=0) wa[tbc++]=i;
_sort(r+2,wa,wb,tbc,m);
_sort(r+1,wb,wa,tbc,m);
_sort(r,wa,wb,tbc,m);
for(p=1,rn[F(wb[0])]=0,i=1; i<tbc; i++)
rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
if(p<tbc) dc3(rn,san,tbc,p);
else for(i=0; i<tbc; i++) san[rn[i]]=i;
for(i=0; i<tbc; i++) if(san[i]<tb) wb[ta++]=san[i]*3;
if(n%3==1) wb[ta++]=n-1;
_sort(r,wb,wa,ta,m);
for(i=0; i<tbc; i++) wv[wb[i]=G(san[i])]=i;
for(i=0,j=0,p=0; i<ta && j<tbc; p++)
sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
for(; i<ta; p++) sa[p]=wa[i++];
for(; j<tbc; p++) sa[p]=wb[j++];
return;
}
void calheight(int *r, int *sa, int n) {
int i, j, k = 0;
for (i = 1; i <= n; i++) Rank[sa[i]] = i;
for (i = 0; i < n; height[Rank[i++]] = k)
for (k ? k-- : 0, j = sa[Rank[i] - 1]; r[i + k] == r[j + k]; k++);
}
//LCP(suffix(i), suffix(j))=RMQ_query(rnk[i], rnk[j]);
int RMQ_query(int l, int r) {
l = Rank[l]; r = Rank[r];
// if(l == r) return dp[l][0];
if (l > r) swap(l, r);
// l++;
int k = 0; while (1<<(k+1) <= r - l + 1) k++;
return min(dp[l][k], dp[r-(1<<k)+1][k]);
}
void RMQ_init(int n) {
for (int i=0; i<n; ++i) dp[i][0] = height[i];
for (int j=1; (1<<j)<=n; ++j) {
for (int i=0; i+(1<<j)-1<n; ++i) {
dp[i][j] = std::min (dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
}
}
}
int n, m;
int k;
int id[MXN], vis[MXN];
char ar[MXN], br[MXN], cr[MXN];
int s[MXN];
int stak[MXN], top;
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
while(~scanf("%d", &k) && k) {
scanf("%s", ar);
for(int i = 0; i <= k; ++i) vis[i] = 0;
int len = strlen(ar);
memcpy(cr, ar, len);
int Max = 128;
for(int i = 0; i < len; ++i) id[i] = 1, s[i] = ar[i];
for(int i = 1; i < k; ++i) {
scanf("%s", br);
s[len] = 'z' + i;ar[len] = 'z' + 1;
Max = big(Max, 'z' + i);
id[len] = 0;
int tmp = strlen(br);
for(int j = 0; j < tmp; ++j) id[len + j + 1] = i + 1, s[len+j+1] = br[j];
memcpy(ar + len + 1, br, tmp);
len += tmp + 1;
}
if(k == 1) {
printf("%s\n", ar);
printf("\n");
continue;
}
ar[len] = '\0';
s[len] = '\0';
dc3(s, sa, len + 1, 256);
calheight(s, sa, len);
RMQ_init(len+1);
top = 0;
int ans = 0, cnt = 1, aim = k/2 + 1, l = 1;
++ vis[id[ sa[1]]];
for(int i = 2; i <= len; ++i) {
if(vis[id[ sa[i]]] == 0 && id[ sa[i]]) ++ cnt;
++ vis[id[ sa[i]]];
if(cnt >= aim) {
int tmp = RMQ_query( sa[l+1], sa[i]);
if(tmp > ans) {
ans = tmp;
top = 0;
stak[++top] = i;
}else if(tmp == ans && ans) {
stak[++top] = i;
}
}
while(l < i && RMQ_query( sa[l+1], sa[i]) == 0) {
-- vis[id[ sa[l]]];
if(id[ sa[l]] && vis[id[ sa[l]]] == 0) -- cnt;
++ l;
if(cnt >= aim) {
int tmp = RMQ_query( sa[l+1], sa[i]);
if(tmp > ans) {
ans = tmp;
top = 0;
stak[++top] = i;
}else if(tmp == ans && ans) {
stak[++top] = i;
}
}
}
while(cnt >= aim && l < i) {
-- vis[id[ sa[l]]];
if(id[ sa[l]] && vis[id[ sa[l]]] == 0) -- cnt;
++ l;
if(cnt >= aim) {
int tmp = RMQ_query( sa[l+1], sa[i]);
if(tmp > ans) {
ans = tmp;
top = 0;
stak[++top] = i;
}else if(tmp == ans && ans) {
stak[++top] = i;
}
}
}
}
for(int i = 0; i <= len; ++i) id[i] = s[i] = 0;
if(ans <= 0) printf("?\n");
else {
vector<string> vs;
for(int i = 1; i <= top; ++i) {
string tmp = "";
for(int j = sa[stak[i]], h = 0; h < ans; ++h, ++j) tmp += ar[j];
vs.eb(tmp);
}
my_unique(vs);
for(int i = 0; i < vs.size(); ++i) {
for(int j = 0; j < ans; ++j) ar[j] = vs[i][j]; ar[ans] = '\0';
printf("%s\n", ar);
}
}
printf("\n");
}
#ifndef ONLINE_JUDGE
cout << "time cost:" << clock() << "ms" << endl;
#endif
return 0;
}
倍增
#pragma comment(linker, "/STACK:102400000,102400000")
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<map>
#include<iostream>
#include<assert.h>
#include <algorithm>
#define fi first
#define se second
#define endl '\n'
#define o2(x) (x)*(x)
#define BASE_MAX 62
#define mk make_pair
#define eb push_back
#define all(x) (x).begin(), (x).end()
#define clr(a,b) memset((a),(b),sizeof((a)))
#define iis std::ios::sync_with_stdio(false); cin.tie(0)
#define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end())
using namespace std;
#pragma optimize("-O3")
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, int> pLi;
inline LL read(){
LL x=0;int f=0;char ch=getchar();
while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x=f?-x:x;
}
inline void write(LL x) {
if(x==0){putchar('0'),putchar('\n');return;}
if(x < 0) {putchar('-');x=-x;}
static char s[23];int l = 0;
while(x!=0)s[l++]=x%10+48,x/=10;
while(l)putchar(s[--l]);
putchar('\n');
}
int lowbit(int x) {return x&(-x);}
template<class T> T big(const T& a1,const T& a2) { return a1>a2?a1:a2; }
//template<typename T, typename ...R> T big (const T& f,const R& ...r) { return big(f, big (r...)); }
template<class T> T sml(const T& a1,const T& a2) { return a1<a2?a1:a2; }
//template<typename T, typename ...R> T sml (const T& f,const R& ...r) { return sml(f, sml (r...)); }
#ifndef ONLINE_JUDGE
void debug_out() { cerr << '\n'; }
template<typename T, typename ...R> void debug_out (const T& f,const R& ...r) { cerr << f << " "; debug_out (r...); }
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
#endif
#define print(x) write(x);
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int HMOD[] = {1000000009, 1004535809};
const LL BASE[] = {1572872831, 1971536491};
const int mod = 1e9 + 6;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int MXN = 2e5 + 7;
struct Suffix_Array {
static const int N = 2e5 + 7;
int n, len, s[N], M;
int sa[N], rnk[N], height[N];
int tmp_one[N], tmp_two[N], c[N];
int dp[N][24];
void init_str(int *str, int _n) {
len = _n;
n = len + 1;
for (int i = 0; i < len; ++i) {
s[i] = str[i];
}
s[len] = '\0';
}
void build_sa(int m = 128);
void calc_height(int n);
void Out(char *str);
void RMQ_init(int n);
int RMQ_query(int l, int r);
int cmp_suffix(char* pattern, int p){//判斷是否爲後綴p的前綴
return strncmp(pattern, reinterpret_cast<const char *>(s + sa[p]), M);
}
int find(char* P){//Omlog(n)
M = strlen(P);
if(cmp_suffix(P, 0) < 0) return -1;
if(cmp_suffix(P, n-1) > 0) return -1;
int L = 0, R = n - 1;
while(R >= L){
int mid = L + (R - L) / 2;
int res = cmp_suffix(P, mid);
if(!res) return mid;
if(res < 0) R = mid - 1; else L = mid + 1;
}
return -1;
}
}SA;
void Suffix_Array::Out(char *str) {
puts ("/*Suffix*/");
for (int i=0; i<n; ++i) {
printf ("%s\n", str+sa[i]);
}
}
//LCP(suffix(i), suffix(j))=RMQ_query(rnk[i], rnk[j]);
int Suffix_Array::RMQ_query(int l, int r) {
l = rnk[l]; r = rnk[r];
// if(l == r) return dp[l][0];
if (l > r) swap(l, r);
// l++;
int k = 0; while (1<<(k+1) <= r - l + 1) k++;
return min(dp[l][k], dp[r-(1<<k)+1][k]);
}
void Suffix_Array::RMQ_init(int n) {
for (int i=0; i<n; ++i) dp[i][0] = height[i];
for (int j=1; (1<<j)<=n; ++j) {
for (int i=0; i+(1<<j)-1<n; ++i) {
dp[i][j] = std::min (dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
}
}
}
void Suffix_Array::calc_height(int n) {
for (int i=0; i<=n; ++i) rnk[sa[i]] = i;
int k = height[0] = 0;
for (int i=0; i<n; ++i) {
if (k) k--;
int j = sa[rnk[i]-1];
while (s[i+k] == s[j+k]) k++;
height[rnk[i]] = k;
}
}
//m = max(r[i]) + 1,一般字符128足夠了
void Suffix_Array::build_sa(int m) {
int i, j, p, *x = tmp_one, *y = tmp_two;
for (i=0; i<m; ++i) c[i] = 0;
for (i=0; i<n; ++i) c[x[i]=s[i]]++;
for (i=1; i<m; ++i) c[i] += c[i-1];
for (i=n-1; i>=0; --i) sa[--c[x[i]]] = i;
for (j=1; j<=n; j<<=1) {
for (p=0, i=n-j; i<n; ++i) y[p++] = i;
for (i=0; i<n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
for (i=0; i<m; ++i) c[i] = 0;
for (i=0; i<n; ++i) c[x[y[i]]]++;
for (i=1; i<m; ++i) c[i] += c[i-1];
for (i=n-1; i>=0; --i) sa[--c[x[y[i]]]] = y[i];
std::swap (x, y);
for (p=1, x[sa[0]]=0, i=1; i<n; ++i) {
x[sa[i]] = (y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+j] == y[sa[i]+j] ? p - 1 : p++);
}
if(p >= n) break;
m=p;
}
calc_height(n-1);
RMQ_init(n);
}
int n, m;
int k;
int id[MXN], vis[MXN];
char ar[MXN], br[MXN], cr[MXN];
int s[MXN];
int stak[MXN], top;
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
int cas = 0;
while(~scanf("%d", &k) && k) {
++ cas;
scanf("%s", ar);
for(int i = 0; i <= k; ++i) vis[i] = 0;
int len = strlen(ar);
memcpy(cr, ar, len);
int Max = 128;
for(int i = 0; i < len; ++i) id[i] = 1, s[i] = ar[i];
for(int i = 1; i < k; ++i) {
scanf("%s", br);
s[len] = 'z' + i;ar[len] = 'z' + 1;
Max = big(Max, 'z' + i);
id[len] = 0;
int tmp = strlen(br);
for(int j = 0; j < tmp; ++j) id[len + j + 1] = i + 1, s[len+j+1] = br[j];
memcpy(ar + len + 1, br, tmp);
len += tmp + 1;
}
// if(cas > 1) printf("\n");
if(k == 1) {
printf("%s\n", ar);
printf("\n");
continue;
}
ar[len] = '\0';
s[len] = '\0';
// debug(ar)
// for(int i = 0; i < len; ++i) printf("%d ", id[i]); printf("\n");
SA.init_str(s, len);
SA.build_sa(Max + 1);
// SA.Out(ar);
top = 0;
int ans = 0, cnt = 1, aim = k/2 + 1, l = 1;
for(int i = 1; i <= len; ++i) {
// printf("* %d ", SA.height[i]);
// printf("%c%c%c\n", ar[SA.sa[i]], ar[SA.sa[i]+1], ar[SA.sa[i]+2]);
}
++ vis[id[SA.sa[1]]];
for(int i = 2; i <= len; ++i) {
// if(cnt == 0 && id[SA.sa[i-1]] && i != 1) ++ cnt, ++ vis[id[SA.sa[i-1]]];
if(vis[id[SA.sa[i]]] == 0 && id[SA.sa[i]]) ++ cnt;
++ vis[id[SA.sa[i]]];
if(cnt >= aim) {
int tmp = SA.RMQ_query(SA.sa[l+1], SA.sa[i]);
if(tmp > ans) {
ans = tmp;
top = 0;
stak[++top] = i;
}else if(tmp == ans && ans) {
stak[++top] = i;
}
}
if(i < 10) {
// printf("%d %d %d %d %d %c%c%c\n", SA.height[i], i, l, cnt, ans, ar[SA.sa[i]], ar[SA.sa[i] + 1], ar[SA.sa[i] + 2]);
// printf("** %d **\n", SA.RMQ_query(SA.sa[l + 1], SA.sa[i]));
}
while(l < i && SA.RMQ_query(SA.sa[l+1], SA.sa[i]) == 0) {
-- vis[id[SA.sa[l]]];
if(id[SA.sa[l]] && vis[id[SA.sa[l]]] == 0) -- cnt;
++ l;
if(cnt >= aim) {
int tmp = SA.RMQ_query(SA.sa[l+1], SA.sa[i]);
if(tmp > ans) {
ans = tmp;
top = 0;
stak[++top] = i;
}else if(tmp == ans && ans) {
stak[++top] = i;
}
}
}
while(cnt >= aim && l < i) {
-- vis[id[SA.sa[l]]];
if(id[SA.sa[l]] && vis[id[SA.sa[l]]] == 0) -- cnt;
++ l;
if(cnt >= aim) {
int tmp = SA.RMQ_query(SA.sa[l+1], SA.sa[i]);
if(tmp > ans) {
ans = tmp;
top = 0;
stak[++top] = i;
}else if(tmp == ans && ans) {
stak[++top] = i;
}
}
}
}
for(int i = 0; i <= len; ++i) id[i] = s[i] = 0;
if(ans <= 0) printf("?\n");
else {
vector<string> vs;
for(int i = 1; i <= top; ++i) {
string tmp = "";
for(int j = SA.sa[stak[i]], h = 0; h < ans; ++h, ++j) tmp += ar[j];
vs.eb(tmp);
}
// sort(all(vs));
my_unique(vs);
for(int i = 0; i < vs.size(); ++i) {
for(int j = 0; j < ans; ++j) ar[j] = vs[i][j]; ar[ans] = '\0';
printf("%s\n", ar);
}
}
printf("\n");
}
#ifndef ONLINE_JUDGE
cout << "time cost:" << clock() << "ms" << endl;
#endif
return 0;
}
//後綴數組(SA[i]存放排名第i大的後綴首字符的下標)
//名次數組(rank[i]存放suffix(i)的優先級(名次))
//height數組:height[i]是Suffix(sa[i-1])和Suffix(sa[i])的最長公共前綴長度
/*SA,R,H的下標都是 0~n 其中多包括了一個空字符串*/
數據
輸入:
2
adsf
asdf
2
fdsa
df
5
abcd
bcde
cdef
defg
efgh
5
nshiyedashai
goanshab
woshidiyi
firstorloser
iamthefirst
4
acaaaaaaaaaaaaa
aaaaa
aa
a
4
aa
a
d
d
2
pabcp
pertp
0
輸出:
a
d
f
s
d
f
cd
de
ef
sh
aa
?
p
題面
POJ 2758 後綴數組
aa[i]
表示的是新字符串的下標i所對應的老字符串的下標
id[i]
表示的是老字符串的下標i所對應的新字符串的下標
is[i] = 1 or 0:
表示新字符串中i這個字符是否來自老字符串
set<int> st
保存老字符串前插入了字符的下標
插入操作不超過;查詢操作不超過.
複雜度
若詢問,先求出,然後通過上面幾個數組求出和距右邊新字符的最近距離
若, 則直接返回
反之從長度開始往後暴力匹配,最多匹配次就會到達字符串邊界或者新的,滿足都是原來的老字符
這樣遞歸處理即可。
SA
#pragma comment(linker, "/STACK:102400000,102400000")
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<cmath>
#include<map>
#include<set>
#include<iostream>
#include<assert.h>
#include <algorithm>
#define fi first
#define se second
#define endl '\n'
#define o2(x) (x)*(x)
#define BASE_MAX 62
#define mk make_pair
#define eb push_back
#define all(x) (x).begin(), (x).end()
#define clr(a,b) memset((a),(b),sizeof((a)))
#define iis std::ios::sync_with_stdio(false); cin.tie(0)
#define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end())
using namespace std;
#pragma optimize("-O3")
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, int> pLi;
inline LL read(){
LL x=0;int f=0;char ch=getchar();
while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x=f?-x:x;
}
inline void write(LL x) {
if(x==0){putchar('0'),putchar('\n');return;}
if(x < 0) {putchar('-');x=-x;}
static char s[23];int l = 0;
while(x!=0)s[l++]=x%10+48,x/=10;
while(l)putchar(s[--l]);
putchar('\n');
}
int lowbit(int x) {return x&(-x);}
template<class T> T big(const T& a1,const T& a2) { return a1>a2?a1:a2; }
//template<typename T, typename ...R> T big (const T& f,const R& ...r) { return big(f, big (r...)); }
template<class T> T sml(const T& a1,const T& a2) { return a1<a2?a1:a2; }
//template<typename T, typename ...R> T sml (const T& f,const R& ...r) { return sml(f, sml (r...)); }
#ifndef ONLINE_JUDGE
void debug_out() { cerr << '\n'; }
template<typename T, typename ...R> void debug_out (const T& f,const R& ...r) { cerr << f << " "; debug_out (r...); }
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
#endif
#define print(x) write(x);
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int HMOD[] = {1000000009, 1004535809};
const LL BASE[] = {1572872831, 1971536491};
const int mod = 1e9 + 6;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int MXN = 3e5 + 7;
struct Suffix_Array {
static const int N = 3e5 + 7;
int n, len, s[N], M;
int sa[N], rnk[N], height[N];
int tmp_one[N], tmp_two[N], c[N];
int dp[N][21];
void init_str(int *str, int _n) {
len = _n;
n = len + 1;
for (int i = 0; i < len; ++i) {
s[i] = str[i];
}
s[len] = '\0';
}
void build_sa(int m = 128);
void calc_height(int n);
void Out(char *str);
void RMQ_init(int n);
int RMQ_query(int l, int r);
int cmp_suffix(char* pattern, int p){//判斷是否爲後綴p的前綴
return strncmp(pattern, reinterpret_cast<const char *>(s + sa[p]), M);
}
int find(char* P){//Omlog(n)
M = strlen(P);
if(cmp_suffix(P, 0) < 0) return -1;
if(cmp_suffix(P, n-1) > 0) return -1;
int L = 0, R = n - 1;
while(R >= L){
int mid = L + (R - L) / 2;
int res = cmp_suffix(P, mid);
if(!res) return mid;
if(res < 0) R = mid - 1; else L = mid + 1;
}
return -1;
}
}SA;
void Suffix_Array::Out(char *str) {
puts ("/*Suffix*/");
for (int i=0; i<n; ++i) {
printf ("%s\n", str+sa[i]);
}
}
int Suffix_Array::RMQ_query(int l, int r) {
l = rnk[l]; r = rnk[r];
if (l > r) swap(l, r);
l++;
int k = 0; while (1<<(k+1) <= r - l + 1) k++;
return min(dp[l][k], dp[r-(1<<k)+1][k]);
}
void Suffix_Array::RMQ_init(int n) {
for (int i=0; i<n; ++i) dp[i][0] = height[i];
for (int j=1; (1<<j)<=n; ++j) {
for (int i=0; i+(1<<j)-1<n; ++i) {
dp[i][j] = std::min (dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
}
}
}
void Suffix_Array::calc_height(int n) {
for (int i=0; i<=n; ++i) rnk[sa[i]] = i;
int k = height[0] = 0;
for (int i=0; i<n; ++i) {
if (k) k--;
int j = sa[rnk[i]-1];
while (s[i+k] == s[j+k]) k++;
height[rnk[i]] = k;
}
}
//m = max(r[i]) + 1,一般字符128足夠了
void Suffix_Array::build_sa(int m) {
int i, j, p, *x = tmp_one, *y = tmp_two;
for (i=0; i<m; ++i) c[i] = 0;
for (i=0; i<n; ++i) c[x[i]=s[i]]++;
for (i=1; i<m; ++i) c[i] += c[i-1];
for (i=n-1; i>=0; --i) sa[--c[x[i]]] = i;
for (j=1; j<=n; j<<=1) {
for (p=0, i=n-j; i<n; ++i) y[p++] = i;
for (i=0; i<n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
for (i=0; i<m; ++i) c[i] = 0;
for (i=0; i<n; ++i) c[x[y[i]]]++;
for (i=1; i<m; ++i) c[i] += c[i-1];
for (i=n-1; i>=0; --i) sa[--c[x[y[i]]]] = y[i];
std::swap (x, y);
for (p=1, x[sa[0]]=0, i=1; i<n; ++i) {
x[sa[i]] = (y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+j] == y[sa[i]+j] ? p - 1 : p++);
}
if(p >= n) break;
m=p;
}
calc_height(n-1);
RMQ_init(n);
}
int n, m;
int k;
int id[MXN], is[MXN], aa[MXN];
char ar[MXN];
int s[MXN];
set<int> st;
/*
aa[i]表示的是新字符串的下標i所對應的老字符串的下標
id[i]表示的是老字符串的下標i所對應的新字符串的下標
is[i] = 1 or 0:表示新字符串中i這個字符是否來自老字符串
set<int> st保存老字符串前插入了字符的下標
插入操作q1不超過200;查詢操作q2不超過20000.
複雜度O(q1×q2)
若詢問(x,y),先求出lcp(Suffix(x), Suffix(y)),然後通過上面幾個數組求出x和y距右邊新字符的最近距離cmin
若lcp > cmin, 則直接返回lcp
反之從cmin長度開始往後暴力匹配,最多匹配200次就會到達字符串邊界或者新的(x',y'),滿足(x',y')都是原來的老字符
這樣遞歸處理即可。
*/
int check(int x, int y) {
if(x > y) swap(x, y);
int lcp = SA.RMQ_query(x, y);
if(st.size() == 0) return lcp;
int lx = *st.lower_bound(x+1), ly = *st.lower_bound(y+1);
// debug(x, y, lcp, lx, ly)
int cmin = INF, len = 0;
if(lx > x) cmin = id[lx-1] - id[x] + 1, len = id[lx] - (lx!=0?id[lx-1]:0);
if(ly > y) cmin = sml(cmin, id[ly-1] - id[y] + 1), len = big(len, id[ly] - (ly!=0?id[ly-1]:0));
if(cmin > lcp) return lcp;
// debug(cmin, len)
len = 201;
for(int i = 1; i <= len; ++i) {
// debug(id[x] + i + cmin - 1, id[y] + i + cmin - 1, s[id[x] + i + cmin - 1] != s[id[y] + i + cmin - 1])
if(s[id[x] + i + cmin - 1] != s[id[y] + i + cmin - 1]) {
return cmin - 1 + i;
}
if(id[y] + i + cmin - 1 == n-1) return cmin + i;
if(is[id[x] + i + cmin - 1] && is[id[y] + i + cmin - 1]) {
// debug(i + cmin - 1, aa[id[x] + i + cmin - 1], aa[id[y] + i + cmin - 1])
return check(aa[id[x] + i + cmin - 1], aa[id[y] + i + cmin - 1]) + i + cmin - 1;
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
scanf("%s", ar);
scanf("%d", &k);
m = n = strlen(ar);
for(int i = 0; i < n; ++i) s[i] = ar[i], aa[i] = id[i] = i, is[i] = 1;
aa[n] = id[n] = n;
SA.init_str(s, n);
SA.build_sa(128);
char op[2];
while(k --) {
scanf("%s", op);
int l, r;
if(op[0] == 'Q') {
scanf("%d%d", &l, &r);
if(l == r) printf("%d\n", n - id[l-1]);
else printf("%d\n", check(l - 1, r - 1));
}else {
scanf("%s%d", op, &r);
if(r > n) r = n + 1;
for (int i = n; i > r - 1; --i) s[i] = s[i - 1], is[i] = is[i-1], aa[i] = aa[i-1];
s[r - 1] = op[0]; is[r-1] = 0;
// aa[r - l] = aa[r];
if(r > n) st.insert(m);
else st.insert(aa[r]);
id[m] = n;
++ n;
for(int i = r; i <= n; ++i) if(is[i]) id[aa[i]] = i;
}
}
#ifndef ONLINE_JUDGE
cout << "time cost:" << clock() << "ms" << endl;
#endif
return 0;
}
//後綴數組(SA[i]存放排名第i大的後綴首字符的下標)
//名次數組(rank[i]存放suffix(i)的優先級(名次))
//height數組:height[i]是Suffix(sa[i-1])和Suffix(sa[i])的最長公共前綴長度
/*SA,R,H的下標都是 0~n 其中多包括了一個空字符串*/
DC3
#pragma comment(linker, "/STACK:102400000,102400000")
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<stack>
#include<map>
#include<iostream>
#include<assert.h>
#include <algorithm>
#include "set"
#define fi first
#define se second
#define endl '\n'
#define o2(x) (x)*(x)
#define BASE_MAX 62
#define mk make_pair
#define eb push_back
#define all(x) (x).begin(), (x).end()
#define clr(a,b) memset((a),(b),sizeof((a)))
#define iis std::ios::sync_with_stdio(false); cin.tie(0)
#define my_unique(x) sort(all(x)),x.erase(unique(all(x)),x.end())
using namespace std;
#pragma optimize("-O3")
typedef long long LL;
typedef pair<int, int> pii;
typedef pair<LL, int> pLi;
inline LL read(){
LL x=0;int f=0;char ch=getchar();
while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x=f?-x:x;
}
inline void write(LL x) {
if(x==0){putchar('0'),putchar('\n');return;}
if(x < 0) {putchar('-');x=-x;}
static char s[23];int l = 0;
while(x!=0)s[l++]=x%10+48,x/=10;
while(l)putchar(s[--l]);
putchar('\n');
}
int lowbit(int x) {return x&(-x);}
template<class T> T big(const T& a1,const T& a2) { return a1>a2?a1:a2; }
//template<typename T, typename ...R> T big (const T& f,const R& ...r) { return big(f, big (r...)); }
template<class T> T sml(const T& a1,const T& a2) { return a1<a2?a1:a2; }
//template<typename T, typename ...R> T sml (const T& f,const R& ...r) { return sml(f, sml (r...)); }
#ifndef ONLINE_JUDGE
void debug_out() { cerr << '\n'; }
template<typename T, typename ...R> void debug_out (const T& f,const R& ...r) { cerr << f << " "; debug_out (r...); }
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__);
#endif
#define print(x) write(x);
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int HMOD[] = {1000000009, 1004535809};
const LL BASE[] = {1572872831, 1971536491};
const int mod = 1e9 + 6;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int MXN = 5e5 + 7;
const int N = 1e6 + 5;
struct DC3 {
static const int N = 1e6 + 5;
int sa[N * 3], height[N], rnk[N];;
int wa[N], wb[N], wv[N], c[N];
int dp[N][24];
int c0(int *r, int a, int b) {
return r[a] == r[b] && r[a + 1] == r[b + 1] && r[a + 2] == r[b + 2];
}
int c12(int k, int *r, int a, int b) {
if (k == 2) return r[a] < r[b] || r[a] == r[b] && c12(1, r, a + 1, b + 1);
else return r[a] < r[b] || r[a] == r[b] && wv[a + 1] < wv[b + 1];
}
void _sort(int *r, int *a, int *b, int n, int m) {
int i;
for (i = 0; i < n; i++) wv[i] = r[a[i]];
for (i = 0; i < m; i++) c[i] = 0;
for (i = 0; i < n; i++) c[wv[i]]++;
for (i = 1; i < m; i++) c[i] += c[i - 1];
for (i = n - 1; i >= 0; i--) b[--c[wv[i]]] = a[i];
return;
}
//dc3.dc3(s, dc3.sa, len + 1, 256);
//dc3.calheight(s, len);
void dc3(int *r, int *sa, int n, int m) {
int i, j, *rn = r + n, *san = sa + n, ta = 0, tb = (n + 1) / 3, tbc = 0, p;
r[n] = r[n + 1] = 0;
for (i = 0; i < n; i++) if (i % 3 != 0) wa[tbc++] = i;
_sort(r + 2, wa, wb, tbc, m);
_sort(r + 1, wb, wa, tbc, m);
_sort(r, wa, wb, tbc, m);
for (p = 1, rn[F(wb[0])] = 0, i = 1; i < tbc; i++)
rn[F(wb[i])] = c0(r, wb[i - 1], wb[i]) ? p - 1 : p++;
if (p < tbc) dc3(rn, san, tbc, p);
else for (i = 0; i < tbc; i++) san[rn[i]] = i;
for (i = 0; i < tbc; i++) if (san[i] < tb) wb[ta++] = san[i] * 3;
if (n % 3 == 1) wb[ta++] = n - 1;
_sort(r, wb, wa, ta, m);
for (i = 0; i < tbc; i++) wv[wb[i] = G(san[i])] = i;
for (i = 0, j = 0, p = 0; i < ta && j < tbc; p++)
sa[p] = c12(wb[j] % 3, r, wa[i], wb[j]) ? wa[i++] : wb[j++];
for (; i < ta; p++) sa[p] = wa[i++];
for (; j < tbc; p++) sa[p] = wb[j++];
return;
}
void calheight(int *r, int n) {
int i, j, k = 0;
for (i = 1; i <= n; i++) rnk[sa[i]] = i;
for (i = 0; i < n; height[rnk[i++]] = k)
for (k ? k-- : 0, j = sa[rnk[i] - 1]; r[i + k] == r[j + k]; k++);
RMQ_init(n + 1);
}
int RMQ_query(int l, int r) {
l = rnk[l], r = rnk[r];
// if(l == r) return dp[l][0];
if (l > r) swap(l, r);
l++;
int k = 0;
while (1 << (k + 1) <= r - l + 1) k++;
return min(dp[l][k], dp[r - (1 << k) + 1][k]);
}
void RMQ_init(int n) {
for (int i = 0; i < n; ++i) dp[i][0] = height[i];
for (int j = 1; (1 << j) <= n; ++j) {
for (int i = 0; i + (1 << j) - 1 < n; ++i) {
dp[i][j] = std::min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
}
}
}
}dc3;
int n, m;
int k;
int id[MXN], is[MXN], aa[MXN];
char ar[MXN];
int s[MXN];
set<int> st;
int check(int x, int y) {
if(x > y) swap(x, y);
int lcp = dc3.RMQ_query(x, y);
if(st.size() == 0) return lcp;
int lx = *st.lower_bound(x+1), ly = *st.lower_bound(y+1);
// debug(x, y, lcp, lx, ly)
int cmin = INF, len = 0;
if(lx > x) cmin = id[lx-1] - id[x] + 1, len = id[lx] - (lx!=0?id[lx-1]:0);
if(ly > y) cmin = sml(cmin, id[ly-1] - id[y] + 1), len = big(len, id[ly] - (ly!=0?id[ly-1]:0));
if(cmin > lcp) return lcp;
// debug(cmin, len)
for(int i = 1; i <= 201; ++i) {
// debug(id[x] + i + cmin - 1, id[y] + i + cmin - 1, s[id[x] + i + cmin - 1] != s[id[y] + i + cmin - 1])
if(s[id[x] + i + cmin - 1] != s[id[y] + i + cmin - 1]) {
return cmin - 1 + i;
}
if(id[y] + i + cmin - 1 == n-1) return cmin + i;
if(is[id[x] + i + cmin - 1] && is[id[y] + i + cmin - 1]) {
// debug(i + cmin - 1, aa[id[x] + i + cmin - 1], aa[id[y] + i + cmin - 1])
return check(aa[id[x] + i + cmin - 1], aa[id[y] + i + cmin - 1]) + i + cmin - 1;
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
scanf("%s", ar);
scanf("%d", &k);
m = n = strlen(ar);
for(int i = 0; i < n; ++i) s[i] = ar[i], aa[i] = id[i] = i, is[i] = 1;
aa[n] = id[n] = n;
dc3.dc3(s, dc3.sa, n + 1, 256);
dc3.calheight(s, n);
char op[2];
while(k --) {
scanf("%s", op);
int l, r;
if(op[0] == 'Q') {
scanf("%d%d", &l, &r);
if(l == r) printf("%d\n", n - id[l-1]);
else printf("%d\n", check(l - 1, r - 1));
}else {
scanf("%s%d", op, &r);
if(r > n) r = n + 1;
for (int i = n; i > r - 1; --i) s[i] = s[i - 1], is[i] = is[i-1], aa[i] = aa[i-1];
s[r - 1] = op[0]; is[r-1] = 0;
// aa[r - l] = aa[r];
if(r > n) st.insert(m);
else st.insert(aa[r]);
id[m] = n;
++ n;
for(int i = r; i <= n; ++i) if(is[i]) id[aa[i]] = i;
}
}
#ifndef ONLINE_JUDGE
cout << "time cost:" << clock() << "ms" << endl;
#endif
return 0;
}
//後綴數組(SA[i]存放排名第i大的後綴首字符的下標)
//名次數組(rank[i]存放suffix(i)的優先級(名次))
//height數組:height[i]是Suffix(sa[i-1])和Suffix(sa[i])的最長公共前綴長度
/*SA,R,H的下標都是 0~n 其中多包括了一個空字符串*/