字串模板筆記

2022-06-07 14:48:11 字數 3574 閱讀 6719

目錄迴圈串字典序

給定字串s,可進行左移操作,求最小(大)字典序及其最小運算元(或有幾個最小字典序,給出所有左移運算元等)。也可用來進行迴圈串計數。

char s[maxn];

int nex[maxn];

int cal_minlex()

return;

}char t[maxn+maxm];

int kmp()

v.push_back(si);

(2)求所有前字尾,即t既是s字首,又是s字尾:

最長是s,次長是\(nex[si-1]\),然後\(i\)跳至\(nex[si-1]\),求i最長\(nex[i]\),其字尾也是\(nex[si-1]\)字尾,以此類推。

cal_next(s, si);

int i=si-1;

v.clear();

v.push_back(si);

while(i>0 && nex[i]>0)

for(int i=(int)v.size()-1; i>=0; i--)

printf("%d ", v[i]);

(3)統計每個字首的出現次數:

字首來自s且尋找s中的匹配數

若\(nex[i]>0\),則\(nex[nex[i]-1]\)一定為以\(s[i]\)結尾的次長字首,以此類推。

memset(ans, 0, sizeof(ans));

for(int i=0; i0; i--) ans[nex[i]-1]+=ans[i];//加上字尾的字首

for(int i=0; i<=si; i++) ans[i]++;//加上自己

字首來自s且尋找t中的匹配數

類似kmp構造s+#+t即可,只關注\(i\geq n+1\)的\(nex[i]\),且最後\(ans\)不用再加1。

(4)統計本質不同的子串數目(連續的):

下面求字串s新增乙個新字元c後,可新增的字串。令t=s+c,反轉得到\(t^\),計算\(t^\)的\(\max(nex[i])\),即最長的出現在s中的字首其長度,且所有更短的字首也出現了。 因此,新增c後新增字串為\(|s|-nex_+1\),其中1為字串t。\(o(n)\)

總複雜度\(o(n^2)\)。

同理,可以計算在頭部新增乙個字元,或者從尾或者頭移除乙個字元時的本質不同子串數目。 當然,移除的變化數目等於新增的變化數目。

多字串匹配:

列舉字首,o(min(si)*sum(si))

#define maxn 213

#define maxm 213

#define inf 426

int nex[maxn+maxm];

char s[maxn], a[4013][maxm];

void cal_next(char s, int si)

return;

}int kmp(int st, int x)

else if(res==ans)

} if(ans<=0) printf("identity lost\n");

else

} return 0;

}

exkmp
z函式:\(z[i]\)為滿足從位置\(i\)開始且為\(s\)字首的字串的最大長度。

從0開始就是\(s\)與\(s[i,n-1]\)的最長公共字首(lcp),\(aaaaa\)是\(04321\)可以超過\(i\)的,並不是只匹配\([0,i)\),\(ababa\)為\(00301\)。

int z[maxn];

void exkmp(char s, int si)

}

manacher
馬拉車:在字串\(s\)中尋找最長回文連續子串。

實際在\(o(n)\)找出以各個\(s[i]\)為中心的半徑。

//使長度變為基數

char s_new[maxn*2];

int p[maxn*2];

int init()

s_new[j] = '\0';//$對應\0

return j;

}int manacher()

return max_len;

}//s從s[0]開始讀入

ac自動機

給出\(n\)個\(s\),求\(a\)中能匹配多少種\(s\),\(o(sun(s.si)+a.si)\)。

只輸出種數:

允許有相同的\(s\),res+=2

#include #define maxn 500013	//sum(s.si)

#define maxm 1000013 //max(s.si, a.si)

using namespace std;

struct ac

void insert(char *s)

e[u]++;

} queueq;

void build()

} }int query(char *t)

} return res;

}};ac ac;

char s[maxm];

int n;

int main()

ac.build();

scanf("%s", s+1);

printf("%d\n", ac.query(s));

} return 0;

}

輸出每種\(s\)的匹配數:

僅有注釋部分有修改,該query()返回最大的匹配數

不允許有相同的\(s\),val[i]中存的以i結束的s(唯一)被匹配的次數

cnt[i]存s[i]的次數

aa被aaaaa匹配4次,而不是2次

#include #define maxn 83	//(s.si)

#define maxm 1000013 //max(s.si, a.si)

#define n 163 //cnt(s)

using namespace std;

struct ac

void insert(char *s, int id)

//e[u]++;

e[u]=id;//以u結束的是第id個s(前提要沒有相同的s)

} queueq;

void build()

} }int query(char *t)

} for(int i=0; i<=tot; i++)

return res;

}};ac ac;

char s[n][maxn], t[maxm];

int n;

int main()

ac.build();

scanf("%s", t+1);

int res=ac.query(t);

printf("%d\n", res);

} return 0;

}

多行字串 模板字串

多行字串 下面是普通字串的寫法 普通字串 var l abcd console.log l 編譯結果 如何讓讓乙個字串獨佔多行呢?就需要用到es6 裡的多行字串 多行字串 var i ab cd console.log i 編譯結果 再說說拼接字串,一般情況我們是如何拼接字串的呢?看下面 正常拼接字...

模板 字串 字串匹配

計算next陣列的方法是對於長度為n的匹配串,從0到n 1位依次求出字首字尾最大匹配長度。下面的寫法是僅僅檢測有沒有匹配然後返回第乙個匹配位置,而不是返回所有匹配位置。include include include using namespace std const int n 100 char s...

字串模板

include include include include using namespace std const int maxn 1e6 7 int next maxn string s,t void get next string str void kmp intmain include in...