傳送門 to hdu
傳送門 to vj
考慮一位一位的加入字元,我們只在乎當前字串末尾的匹配情況。
既然如此,我們用 acac
ac自動機上的乙個節點來表示狀態就可以了。
現在是乙個 dpdp
dp轉移。似乎要儲存是否曾經出現過詞根?
其實不用,只需要用所有情況減去一次都沒有出現過的情況即可。
向量中加入乙個值,用來求累和——就不需要考慮不轉移的情況了。
並且是常係數。所以使用矩陣加速。複雜度 o(n
6logl
)\mathcal o(n^6\log l)
o(n6
logl) 。
重大坑點(我因此 wawa
wa了很多次):乙個節點是否為「沒有出現過詞根」,要檢查其 fai
lfail
fail
指標,而不是單純地考慮當前這個點是否為單詞末尾。詳見** 64
6464
行。
#include
#include
#include
#include
using
namespace std;
inline
intreadint()
inline
void
writeint
(long
long x)
# define mb template < typename t >
mb void
getmax
(t &a,
const t &b)
mb void
getmin
(t &a,
const t &b)
const
int maxn =27;
namespace acmachine node[maxn]
;int cntnode;
intnewnode()
void
clear()
void
insert
(char s,
int val)
node[o]
.val = val;
}int q[maxn]
;void
build()
else node[o]
.son[i]
= d;
}// 重大坑點!這個點即使不是直接的末尾,實際上也匹配完成了!
getmax
(node[o]
.val,node[node[o]
.fail]
.val)
;// 重大坑點!這個點即使不是直接的末尾,實際上也匹配完成了!}}
}using
namespace acmachine;
typedef
unsigned
long
long int_;
struct matrix
matrix operator*(
const matrix &b)
const
matrix &
operator*=
(const matrix &b)};
matrix qkpow
(matrix base,int_ q)
int_ dengbi
(int_ base,
int q)
return ans;
}char s[10]
;int n, l;
matrix movement, origin;
intmain()
for(
int i=
0; i<=cntnode;
++i)
if(node[i]
.val ==0)
movement.a[i]
[maxn-1]
=-1;
// 統計答案
movement.a[maxn-1]
[maxn-1]
=1;// 求累加
origin.a[0]
[0]=
1;// 從 null 出發
origin.a[0]
[maxn-1]
=dengbi(26
,l)+1;
origin *
=qkpow
(movement,
int_
(l)+
1ull);
cout << origin.a[0]
[maxn-1]
<< endl;
}return0;
}
hdu 2243 考研路茫茫 單詞情結
hdoj 2243 不僅僅是考研路茫茫 a此題的過程也是路茫茫 終於到最後柳暗花明了 a這個題用了3天 或者說用了1個月 因為1個月前就學了kmp和ac自動機 雖然上個月那節課學了kmp匹配演算法 字典樹 ac自動機。當時就聽得一頭霧水 特別是kmp那個失敗指標 或者說成是next fail.有那麼...
HDU 2243 考研路茫茫 單詞情結
這道題和poj2778類似都需要利用end陣列和next陣列的特性構建狀態陣列,不過這裡是需要經過至少乙個目標串,而且長度是不小於l的,即需要長度為1 l時的種數和。然後我們可以求出總數後減去不經過目標串的和,剩下的就是我們要的答案。設總數的陣列為f n 當n為1時答案為26,n為2時為26 26 ...
hdu 2243 考研路茫茫 單詞情結
題目大意 問長度為1 n的串中包含了模式串的串總共有幾個。題目思路 求出長度不大於l的包含模式串的字串數,方法是改求不包含模式串的字串總數,當然先要處理出總的字串個數,可以用矩陣也可以用二分冪和的方法。而求不包含模式串的字串數同樣是構造矩陣,同時還要建立乙個虛結點,儲存長度小於l的不包含模式串的字串...