題目鏈結
由於是許可權題,我沒有許可權號,就掛了乙個darkbzoj的鏈結。
題意:給你n
nn個字串,每個串有乙個價值,你要從中選出乙個價值和最大的子串行,使得前面的串是後面串的子串。資料組
數<=10
,總串長
<=3
e5,單
個串
長<=2
e4
資料組數<=10,總串長<=3e5,單個串長<=2e4
資料組數
<=1
0,總串
長<=3
e5,單
個串長<=2
e4。題解:
一看到子串不一定就是sa和sam的題啊,這個題就是用ac自動機的題。
那麼我們就先對於這n
nn個串建出ac自動機。我們考慮如何用ac自動機來判斷乙個串是否是另乙個串的子串。做法是,我們知道,ac自動機上的fail指標的含義是如果當前位置匹配失敗,下一次應該在哪個串的基礎上繼續嘗試匹配。那麼如果乙個串a
aa是另乙個串b
bb的子串,那麼就意味著b
bb在trie樹上的所有節點中,至少有乙個在若干次失配後會到達a
aa在trie樹上的結束節點。那麼如果我們根據fail指標的關係建出fail樹,a
aa串結束節點在fail樹上的子樹內一定有乙個節點是b
bb串在trie樹上的節點。我們可以發現,乙個點表示的串一定是fail樹中的子節點表示的串的乙個子串,同時似乎也是乙個字尾。(總
串長∗l
og
)o(總串長*log)
o(總串長∗
log)
的,可以通過本題。
**:
#include
using
namespace std;
int t,n,val[
200010
],num,fail[
300010
],hed[
300010
],cnt,xu[
300010
],ed[
300010];
int f[
200010
],ans;
vector<
char
> v[
200010];
queue<
int> q;
char ss[
300010];
struct node
t[300010];
struct edge
a[600010];
struct tree
tr[2000010];
inline
void
insert
(int qwq)
cur=t[cur]
.vis[x];}
}inline
void
get_fail()
}while
(!q.
empty()
)if(cur==1)
break
; cur=fail[cur];}
fail[x]
=cur;
}for
(int i=
0;i<26;
++i)}}
inline
void
add(
int from,
int to)
inline
void
dfs(
int x)
ed[x]
=cnt;
}inline
void
build
(int rt,
int l,
int r)
inline
void
pushdown
(int rt)
}inline
intquery
(int rt,
int le,
int ri)
inline
void
update
(int rt,
int le,
int ri,
int y)
pushdown
(rt)
;int mid=
(l+r)
>>1;
if(le<=mid)
update
(rt<<
1,le,ri,y);if
(mid+
1<=ri)
update
(rt<<1|
1,le,ri,y)
; tr[rt]
.mx=
max(tr[rt<<1]
.mx,tr[rt<<1|
1].mx);}
intmain()
num=1;
ans=0;
memset
(fail,0,
sizeof
(fail));
memset
(hed,0,
sizeof
(hed));
memset
(xu,0,
sizeof
(xu));
memset
(ed,0,
sizeof
(ed));
memset
(f,0
,sizeof
(f))
;scanf
("%d"
,&n)
;for
(int i=
1;i<=n;
++i)
for(
int i=
1;i<=n;
++i)
insert
(i);
get_fail()
;for
(int i=
1;i<=num;
++i)
add(fail[i]
,i);
cnt=0;
dfs(1)
;build(1
,1,num)
;for
(int i=
1;i<=n;
++i)
f[i]
=val[i]
+max
(mx,0)
;update(1
,xu[cur]
,ed[cur]
,f[i]);
}for
(int i=
1;i<=n;
++i)
ans=
max(ans,f[i]);
printf
("%d\n"
,ans)
;for
(int i=
1;i<=n;
++i)
v[i]
.clear()
;}return0;
}
BZOJ 3172 單詞 (AC自動機)
這道題是個裸的ac自動機,但是我還是調了很久qaq。首先如果我們直接用每個單詞來匹配的,時間不是很理想。這道題要用到ac自動機的衍生物 fail樹 我也是做這道題才知道有這個東西 fail樹有這麼乙個結論 乙個字串出現的次數等於以它為根節點的fail樹的子樹中所有節點的cnt的和。根據這個結論,我們...
bzoj3172 單詞 AC自動機
感覺以前寫過。bzoj上不去我也不知道 跑一遍ac自動機,每乙個節點儲存一下屬於多少字串,為它的權值。然後乙個節點表示的字串在整個字典中出現的次數相當於其在fail樹中的子樹的權值的和。ac自動機不要寫掛就好了。ac 如下 include include include define n 11000...
bzoj3172 單詞 AC自動機
有n個單詞組成了一篇文章,求每個單詞在這篇文章中出現了多少次。多個字串匹配的問題,建立ac自動機。如果某個單詞在i節點出現了,那麼在i節點fail指標所指節點也出現過。code include include using namespace std const int max n 1000005 s...