在sam中,state_ai->nxt[w] == stateb ( w: const )stateb->fa->step <= state_ai->step ( state_ai->nxt[w] == stateb )
利用拓撲排序,可構建所有子串在原串中出現的次數
sam中的每個狀態點都表示為從root出發走到該點所構成的子串,若其作為其他狀態的父節點,則說明該子串被其他子串共享。求出現兩次以上且不重複的子串數量只要對每個點記錄最早最晚出現的位置
兩位置間距大於所表示的串長,res += p->step - p->fa->step
否則,取其中的部分
#include #include #include #include using namespace std;
const int maxn = 1010;
char s[maxn ];
struct node
} *root, *tail, nodepool[maxn << 1], *cur, *cnt;
void init()
void insert ( int w )
if ( !p )
else
else}}
tail = np;
}int c[maxn]; node *seq[maxn << 1];
void solve()
memset ( c, 0, sizeof c );
for ( int i = 0; i < cur - nodepool; ++i )
for ( int i = 1; i <= tail->pos; ++i )
for ( int i = 0; i < cur - nodepool; ++i )
for ( int i = cur - nodepool - 1; i >= 0; --i )
if ( p->fa )
if ( q->lst == 0 || q->lst < p->lst ) }}
int res = 0;
for ( p= root+1; p< cur; ++p) }
printf("%d\n", res);
}int main()
solve();
}return 0;
}
菜鳥從未碰過cf,通過大神們的部落格找到這題
開始還一直卡在如何確定當前已匹配長度串在sam中的位置,果然理解還是不夠
#include #include #include #include #include using namespace std;
const int maxn = 1000010;
typedef long long ll;
char s[maxn << 1];
struct node
} *root, *tail, nodepool[maxn << 1], *cur;
void init()
void insert ( int w )
if ( !p )
else
else}}
tail = np;
}int c[maxn]; node *seq[maxn << 1];
void preinit()
for ( int i = 1; i <= tail->step; ++i )
for ( int i = 0; i < cur - nodepool; ++i )
a = root;
for ( char *st = s; *st; ++st )
for ( int i = cur - nodepool - 1; i >= 0; --i )
}}void solve ( int cao )
else
if ( !p )
else
}if ( i >= l - 1 && sum >= l )
q = q->fa;
}if ( q->*** != cao )}}
cout << res << endl;
}int main()
preinit();
scanf ( "%d", &n );
for ( int i = 1; i <= n; ++i )
return 0;
}
主要考對sam基礎的理解,還有些煩到死的優化
#include #include #include #include #include using namespace std;
const int maxn = 260000;
typedef long long ll;
char s[maxn];
int n, m, k;
int res;
struct node
} *root, *tail, nodepool[maxn << 1], *cur;
void init()
void insert ( int w )
if ( !p )
}else
q = q->fa;}}
else
for ( node *as = q->fa; as != root && !as->flag; as = as->fa )
}if ( q->num >= k )
q->fa = np->fa = r;
if ( q->num >= k )
if ( np->num >= k )
for ( ; p && p->nxt[w] == q; p = p->fa ) }}
tail = np;
}int main()
int a;
while ( m-- )
else}}
return 0;
}
字尾自動機合集 I
有關字尾自動機的理論和證明各路大神的部落格多如牛毛,就不細說。貼圖太佔載入速度了,還是去看原版的解析吧 對於每個state點,father指向與該節點可接收相同字尾的節點,其表示的字串通常是當前節點表示字串的後面部分,因此state step sate father step 代表從任一字尾串起始走...
字尾自動機
基礎知識 step i 表示的是字串i在原字串中的位置。pareint i 表示root到parent i 的子串是root到i的最長字尾。字尾自動機遍歷可以得到原字串的所有子串。特殊技巧 一 字尾自動機的不同子串數有兩種求法 1.ans step i step parent i 1 i cnt 2...
字尾自動機
常用於處理字串問題,可以高效解決許多字串問題。有點像將乙個字串的所有字尾都建在乙個ac自動機上,但不同的是字尾自動機的節點數最多為2 n,因為它只記錄需要記錄的點,一些沒有記錄東西的點可以視為與下面有價值的節點並在一起,這樣大大降低了時間複雜度和空間複雜度。對於每乙個節點記錄它的後面加上每個字元後字...