From cxlove
资料
http://fanhq666.blog.163.com/blog/static/8194342620123352232937/
题目
http://www.spoj.pl/problems/NSUBSTR/
这题基本上就是套个木板T_T 。 借鉴的cxlove 和 UESTC 神奇的 后缀三兄弟 Orz
const int N = 250009;
namespace SAM{
const int CHAR = 26;
const int LEN = N << 1;
struct SAM_Node{
SAM_Node *fa , *son[CHAR];
int len , id , pos , g;
SAM_Node(){}
SAM_Node(int _len){
g = 0;
fa = 0;
len = _len;
RST(son);
}
};
SAM_Node node[LEN << 1] , *root , *last;
int SAM_size;
SAM_Node * newNode(int len){
node[SAM_size] = SAM_Node(len);
node[SAM_size].id = SAM_size;
return &node[SAM_size++];
}
SAM_Node *newNode(SAM_Node * p){
node[SAM_size] = *p;
node[SAM_size].id = SAM_size;
return &node[SAM_size++];
}
void init(){
SAM_size = 0;
root = last = newNode(0);
node[0].pos = 0;
}
void add(int x , int len){
SAM_Node *p = last , *np = newNode(p -> len + 1);
np -> pos = len;
last = np;
for( ; p && !p -> son[x] ; p = p -> fa)
p -> son[x] = np;
if (!p){
np -> fa = root;
return;
}
SAM_Node *q = p -> son[x];
if (q -> len == p -> len + 1){
np -> fa = q;
return;
}
SAM_Node * nq = newNode(q);
nq -> len = p -> len + 1;
q -> fa = nq;
np -> fa = nq;
for ( ; p && p -> son[x] == q ; p = p -> fa)
p -> son[x] = nq;
}
void build(char * s){
init();
int len = strlen(s);
REP(i , len)
add(s[i] - 'a' , i + 1);
}
}using namespace SAM;
char str[N];
int dp[N] , n , topocnt[N];
SAM_Node *topsam[LEN];
void solve(){
n = strlen(str);
build(str);
RST(topocnt);
REP(i , SAM_size)
topocnt[node[i].len] ++;
REP_1(i , n) topocnt[i] += topocnt[i - 1];
REP(i , SAM_size) topsam[ -- topocnt[node[i].len] ] = &node[i];
REP(i , n) (root = root -> son[str[i] - 'a']) -> g++;
RST(dp);
for (int i = SAM_size - 1 ; i > 0 ; i--){
checkMax(dp[ topsam[i] -> len ] , topsam[i] -> g);
if (topsam[i] -> fa) topsam[i] -> fa -> g += topsam[i] -> g;
}
for (int i = n - 1 ; i > 0 ; i--) checkMax(dp[i] , dp[i + 1]);
REP_1(i , n) printf("%d\n" , dp[i]);
}
int main(){
while(~scanf("%s" , str)) solve();
}
http://www.spoj.pl/problems/LCS/
const int N = 250009;
const int CHAR = 26;
namespace SAM{
struct Node{
Node * fa , *next[CHAR];
int len , id , pos;
Node(){}
Node(int _len){
fa = 0;
len = _len;
RST(next);
}
};
Node node[N << 1] , *root , *last;
int size;
Node * newnode(int len){
node[size] = Node(len);
node[size].id = size;
return &node[size++];
}
Node * newnode(Node * p){
node[size] = *p;
node[size].id = size;
return &node[size++];
}
void init(){
size = 0;
root = last = newnode(0);
node[0].pos = 0;
}
void add(int x , int len){
Node *p = last , *np = newnode(p -> len + 1);
np -> pos = len;
last = np;
for( ; p && !p -> next[x] ; p = p -> fa)
p -> next[x] = np;
if (!p){
np -> fa = root;
return;
}
Node *q = p -> next[x];
if (q -> len == p -> len + 1){
np -> fa = q;
return;
}
Node * nq = newnode(q);
nq -> len = p -> len + 1;
q -> fa = nq;
np -> fa = nq;
for( ; p && p -> next[x] == q ; p = p -> fa)
p -> next[x] = nq;
}
void build(char * s){
init();
int l = strlen(s);
REP(i , l)
add(s[i] - 'a' , i + 1);
}
}using namespace SAM;
char str[N] , s[N];
int ans , l , n , topcnt[N];
Node* topo[N << 1] , *now;
void solve(){
n = strlen(str);
build(str);
RST(topcnt);
REP(i , size)
topcnt[node[i].len]++;
REP_1(i , n) topcnt[i] += topcnt[i - 1];
REP(i , size) topo[ -- topcnt[node[i].len] ] = &node[i];
n = strlen(s);
ans = 0 , l = 0;
now = root;
REP(i , n){
int x = s[i] - 'a';
if(now -> next[x]){
l++;
now = now -> next[x];
}
else{
while(now && now -> next[x] == NULL)
now = now -> fa;
if (!now){
l = 0;
now = root;
}
else{
l = now -> len + 1;
now = now -> next[x];
}
}
checkMax(ans , l);
}
OT(ans);
}
int main(){
while(~scanf("%s%s" , str , s)) solve();
}
http://www.spoj.pl/problems/LCS2/
const int N = 250009;
const int CHAR = 26;
namespace SAM{
struct Node{
Node * fa , *next[CHAR];
int len , id , pos;
Node(){}
Node(int _len){
fa = 0;
len = _len;
RST(next);
}
};
Node node[N << 1] , *root , *last;
int size;
Node * newnode(int len){
node[size] = Node(len);
node[size].id = size;
return &node[size++];
}
Node * newnode(Node * p){
node[size] = *p;
node[size].id = size;
return &node[size++];
}
void init(){
size = 0;
root = last = newnode(0);
node[0].pos = 0;
}
void add(int x , int len){
Node *p = last , *np = newnode(p -> len + 1);
np -> pos = len;
last = np;
for( ; p && !p -> next[x] ; p = p -> fa)
p -> next[x] = np;
if (!p){
np -> fa = root;
return;
}
Node *q = p -> next[x];
if (q -> len == p -> len + 1){
np -> fa = q;
return;
}
Node * nq = newnode(q);
nq -> len = p -> len + 1;
q -> fa = nq;
np -> fa = nq;
for( ; p && p -> next[x] == q ; p = p -> fa)
p -> next[x] = nq;
}
void build(char * s){
init();
int l = strlen(s);
REP(i , l)
add(s[i] - 'a' , i + 1);
}
}using namespace SAM;
char str[N] , s[N];
int ans , l , n , topcnt[N];
Node* topo[N << 1] , *now;
void solve(){
n = strlen(str);
build(str);
RST(topcnt);
REP(i , size)
topcnt[node[i].len]++;
REP_1(i , n) topcnt[i] += topcnt[i - 1];
REP(i , size) topo[ -- topcnt[node[i].len] ] = &node[i];
n = strlen(s);
ans = 0 , l = 0;
now = root;
REP(i , n){
int x = s[i] - 'a';
if(now -> next[x]){
l++;
now = now -> next[x];
}
else{
while(now && now -> next[x] == NULL)
now = now -> fa;
if (!now){
l = 0;
now = root;
}
else{
l = now -> len + 1;
now = now -> next[x];
}
}
checkMax(ans , l);
}
OT(ans);
}
int main(){
while(~scanf("%s%s" , str , s)) solve();
}
const int N = 100009;
const int CHAR = 26;
namespace SAM{
struct Node{
Node * fa , *next[CHAR];
int len , id , pos;
int curlen , minlen;
Node(){}
Node(int _len){
fa = 0;
len = _len;
RST(next);
}
};
Node node[N << 1] , *root , *last;
int size;
Node * newnode(int len){
node[size] = Node(len);
node[size].id = size;
return &node[size++];
}
Node * newnode(Node * p){
node[size] = *p;
node[size].id = size;
return &node[size++];
}
void init(){
size = 0;
root = last = newnode(0);
node[0].pos = 0;
}
void add(int x , int len){
Node *p = last , *np = newnode(p -> len + 1);
np -> pos = len;
last = np;
for( ; p && !p -> next[x] ; p = p -> fa)
p -> next[x] = np;
if (!p){
np -> fa = root;
return;
}
Node *q = p -> next[x];
if (q -> len == p -> len + 1){
np -> fa = q;
return;
}
Node * nq = newnode(q);
nq -> len = p -> len + 1;
q -> fa = nq;
np -> fa = nq;
for( ; p && p -> next[x] == q ; p = p -> fa)
p -> next[x] = nq;
}
void build(char * s){
init();
int l = strlen(s);
REP(i , l)
add(s[i] - 'a' , i + 1);
}
}using namespace SAM;
char str[N];
int ans , l , n , topcnt[N];
Node* topo[N << 1] , *now;
void solve(){
n = strlen(str);
build(str);
RST(topcnt);
REP(i , size)
topcnt[node[i].len]++;
REP_1(i , n) topcnt[i] += topcnt[i - 1];
for (int i = size - 1 ; i >= 0 ; --i) topo[ -- topcnt[node[i].len] ] = &node[i];
REP(i , size){
topo[i] -> minlen = topo[i] -> len;
}
while(~scanf("%s" , str)){
REP(i , size) topo[i] -> curlen = 0;
int len = 0; now = root;
REP_C(i , strlen(str)){
// OT(str[i]);
int x = str[i] - 'a';
while(now -> fa && now -> next[x] == NULL) now = now -> fa , len = now -> len;
if(now -> next[x]){
len++;
now = now -> next[x];
checkMax(now -> curlen , len);
}
else{
len = 0;
now = root;
}
}
for (int i = size - 1 ; i >= 0 ; --i){
now = topo[i];
checkMin(now -> minlen , now -> curlen);
if (now -> fa) checkMax(now -> fa -> curlen , now -> curlen);
}
}
ans = 0;
for (int i = 0 ; i < size ; ++i)
checkMax(ans , node[i].minlen);
OT(ans);
}
int main(){
scanf("%s" , str); solve();
}
http://www.spoj.pl/problems/SUBLEX/
http://acm.hdu.edu.cn/showproblem.php?pid=4436
http://acm.hdu.edu.cn/showproblem.php?pid=4416
http://acm.hdu.edu.cn/showproblem.php?pid=4270
http://codeforces.com/contest/235/problem/C
const int N = 100009;
const int CHAR = 26;
namespace SAM{
struct Node{
Node * fa , *next[CHAR];
int len , id , pos;
int curlen , minlen;
Node(){}
Node(int _len){
fa = 0;
len = _len;
RST(next);
}
};
Node node[N << 1] , *root , *last;
int size;
Node * newnode(int len){
node[size] = Node(len);
node[size].id = size;
return &node[size++];
}
Node * newnode(Node * p){
node[size] = *p;
node[size].id = size;
return &node[size++];
}
void init(){
size = 0;
root = last = newnode(0);
node[0].pos = 0;
}
void add(int x , int len){
Node *p = last , *np = newnode(p -> len + 1);
np -> pos = len;
last = np;
for( ; p && !p -> next[x] ; p = p -> fa)
p -> next[x] = np;
if (!p){
np -> fa = root;
return;
}
Node *q = p -> next[x];
if (q -> len == p -> len + 1){
np -> fa = q;
return;
}
Node * nq = newnode(q);
nq -> len = p -> len + 1;
q -> fa = nq;
np -> fa = nq;
for( ; p && p -> next[x] == q ; p = p -> fa)
p -> next[x] = nq;
}
void build(char * s){
init();
int l = strlen(s);
REP(i , l)
add(s[i] - 'a' , i + 1);
}
}using namespace SAM;
char str[N];
int ans , l , n , topcnt[N];
Node* topo[N << 1] , *now;
void solve(){
n = strlen(str);
build(str);
RST(topcnt);
REP(i , size)
topcnt[node[i].len]++;
REP_1(i , n) topcnt[i] += topcnt[i - 1];
for (int i = size - 1 ; i >= 0 ; --i) topo[ -- topcnt[node[i].len] ] = &node[i];
REP(i , size){
topo[i] -> minlen = topo[i] -> len;
}
while(~scanf("%s" , str)){
REP(i , size) topo[i] -> curlen = 0;
int len = 0; now = root;
REP_C(i , strlen(str)){
// OT(str[i]);
int x = str[i] - 'a';
while(now -> fa && now -> next[x] == NULL) now = now -> fa , len = now -> len;
if(now -> next[x]){
len++;
now = now -> next[x];
checkMax(now -> curlen , len);
}
else{
len = 0;
now = root;
}
}
for (int i = size - 1 ; i >= 0 ; --i){
now = topo[i];
checkMin(now -> minlen , now -> curlen);
if (now -> fa) checkMax(now -> fa -> curlen , now -> curlen);
}
}
ans = 0;
for (int i = 0 ; i < size ; ++i)
checkMax(ans , node[i].minlen);
OT(ans);
}
int main(){
scanf("%s" , str); solve();
}