碰巧今天是NOIP(CSP)复赛日,学弟学妹们冲鸭!rp++!

不存在的分割线

1.字符串数据常用函数

关于char:

复制 strcpy

int main()
{char src[]="abcde";char dest[100];strcpy(dest,src);printf("%s",dest);//输出>> abcde
}

部分复制strncpy

int main()
{char src[]="SWT is so great! We should % him everyday.";char dest[100];memset(dest,0,sizeof(dest));strncpy(dest,src,10);printf("%s\n",dest);//输出>>SWT is so memset(dest,0,sizeof(dest));strncpy(dest,src,sizeof(src));printf("%s\n",dest);//输出>>SWT is so great! We should % him everyday.memset(dest,0,sizeof(dest));strncpy(dest,src,sizeof(dest));printf("%s\n",dest);//输出>>SWT is so great! We should % him everyday.char des[10];memset(des,0,sizeof(des));strncpy(des,src,sizeof(src));printf("%s\n",des);//exe停止工作
}

合并strcat
把src所指字符串添加到dest结尾处(覆盖dest结尾处的 ‘\0’)并添加 ‘\0’


int main()
{char src[]="OI!";char dest[]="We like ";strcat(dest,src);printf("%s",dest);//输出>>We like OI!
}

部分合并strncat


int main()
{char src[]="Please login in here!#$%@$@%@#$@%";char dest[]="Welcome to the largest talking room of SLYZ! ";strncat(dest,src,21);printf("%s",dest);//输出>>Welcome to the largest talking room of SLYZ! Please login in here!
}

查找字符strchr

int main()
{char src[]="Can you find some thing?";int t=strchr(src,'?')-src;printf("%d",t);//输出>>23
}

查找字符串strchr
char* strstr(char* haystack, char* needle);
从字符串haystack中寻找needle第一次出现的位置(不比较结束符”\0”)

#include<cstdio>
#include<cstring>
#include<iostream>using namespace std;int main()
{char src[]="Can you find some thing?";int t=strstr(src,"thing")-src;printf("%d",t);//输出>>18
}

比较strcmp
比较字符串s1和s2,区分大小写
当s1 < s2时,返回值<0;
当s1 = s2时,返回值=0;
当s1 > s2时,返回值>0

int main()
{char src[]="Hello!";char dest[]="hello!";if (!strcmp(src,dest)) printf("SAME");else printf("DIFFERENT");//输出>>DIFFERENT
}

*下面的函数并不常用 *

不区分字母的大小写的比较stricmp
比较字符串s1和s2,但不区分字母的大小写
当s1 < s2时,返回值<0;
当s1 = s2时,返回值=0;
当s1 > s2时,返回值>0

int main()
{char src[]="Hello!";char dest[]="hello!";if (!stricmp(src,dest)) printf("SAME");else printf("DIFFERENT");//输出>>SAME
}

部分比较且区分字母的大小写strncmp

int main()
{char src[]="A APPLE A DAY.";char dest[]="a apple a day.";if (strncmp(src,dest,8)==0) printf("SAME");else printf("DIFFERENT");//输出>>DIFFERENT
}

部分比较,不区分字母的大小写strnicmp

int main()
{char src[]="A APPLE A DAY.";char dest[]="a apple a day.";if (strnicmp(src,dest,8)==0) printf("SAME");else printf("DIFFERENT");//输出>>SAME
}

转化之小写转大写strupr
只转换s中出现的小写字母,不改变其它字符
返回指向s的指针

int main()
{char s[]="Let's % SWT together!";strupr(s);printf("%s",s);//输出>>LET'S % SWT TOGETHER!
}

大写转小写 strlwr
将字符串s转换为小写形式
只转换s中出现的大写字母,不改变其它字符
返回指向s的指针

int main()
{char s[]="Let's % SWT together!";strlwr(s);printf("%s",s);//输出>>let's % swt together!
}

倒置strrev

int main()
{char s[]="!uoy kcor lliw eW";strrev(s);printf("%s",s);//输出>>We will rock you!
}

strset(设置)
把字符串s中的所有字符都设置成字符c

int main()
{char s[]="(!@&*#$^*@#&^(!@#*))";strset(s,'%');printf("%s",s);//输出>>%%%%%%%%%%%%%%%%%%%%
}

关于string:

利用迭代器遍历

我们可以使用类似C中的数组形式访问 s[1]也可以使用STL特有的迭代器访问:
string::iterator it;
for (it = s1.begin(); it != s1.end(); it++)
{cout << *it << endl;
}

重载运算符

s1 = s2;s1 += s2;s1 = s2 + s3;s1 == s2;s1 = "s" + s2; //正确s1 = "s" + "s"; //错误,加号两边至少要有一个string类型的对象s1 = "s" + s2 + "s" + "s"; //正确“+”的两边要保证至少有一个string类型,所以5正确,6错误。
由于在C/C++中,+的返回值还是原类型,所以第7行中,"s"+s2返回一个string类型,
因此string+“s”也是正确的,

插入insert

string s1 = "hello";
s1.insert(1,"ins");//从s1的1位置开始,插入"ins"字符串,即s1="hinsello";
s1.insert(1, "ins", 2);
//从s1的1位置开始,插入"ins"字符串的前2个字符,即s1="hinello";
s1.insert(1, "ins", 1, 2);
//从s1的1位置开始,插入"ins"字符串的从1位置开始的2个字符,即s1="hnsello";iterator insert(iterator it, char c);//在it处插入字符c,返回插入后迭代器的位置

删除rease

iterator erase(iterator first, iterator last);
//删除[first,last)之间的所有字符,返回删除后迭代器的位置

查找find
注意nops


cout << s.find("aa", 0) << endl;
//返回的是子串位置。第二个参数是查找的起始位置,如果找不到,就返回string::npos
if (s.find("aa1", 0) == string::npos)
{cout << "找不到该子串!" << endl;
}

部分选取substr

string ss = s.substr(i,k);//复制s从i开始k个字符给ss

.
.
.
一道利用STL实现字符串哈希的例题
Businesses like to have memorable telephone numbers. One way to make a telephone number memorable is to have it spell a memorable word or phrase. For example, you can call the University of Waterloo by dialing the memorable TUT-GLOP. Sometimes only part of the number is used to spell a word. When you get back to your hotel tonight you can order a pizza from Gino’s by dialing 310-GINO. Another way to make a telephone number memorable is to group the digits in a memorable way. You could order your pizza from Pizza Hut by calling their ``three tens’’ number 3-10-10-10.

The standard form of a telephone number is seven decimal digits with a hyphen between the third and fourth digits (e.g. 888-1200). The keypad of a phone supplies the mapping of letters to numbers, as follows:

A, B, and C map to 2
D, E, and F map to 3
G, H, and I map to 4
J, K, and L map to 5
M, N, and O map to 6
P, R, and S map to 7
T, U, and V map to 8
W, X, and Y map to 9

There is no mapping for Q or Z. Hyphens are not dialed, and can be added and removed as necessary. The standard form of TUT-GLOP is 888-4567, the standard form of 310-GINO is 310-4466, and the standard form of 3-10-10-10 is 310-1010.

Two telephone numbers are equivalent if they have the same standard form. (They dial the same number.)

Your company is compiling a directory of telephone numbers from local businesses. As part of the quality control process you want to check that no two (or more) businesses in the directory have the same telephone number.

Input
The input will consist of one case. The first line of the input specifies the number of telephone numbers in the directory (up to 100,000) as a positive integer alone on the line. The remaining lines list the telephone numbers in the directory, with each number alone on a line. Each telephone number consists of a string composed of decimal digits, uppercase letters (excluding Q and Z) and hyphens. Exactly seven of the characters in the string will be digits or letters.
Output
Generate a line of output for each telephone number that appears more than once in any form. The line should give the telephone number in standard form, followed by a space, followed by the number of times the telephone number appears in the directory. Arrange the output lines by telephone number in ascending lexicographical order. If there are no duplicates in the input print the line:

No duplicates.
Sample Input
12
4873279
ITS-EASY
888-4567
3-10-10-10
888-GLOP
TUT-GLOP
967-11-11
310-GINO
F101010
888-1200
-4-8-7-3-2-7-9-
487-3279
Sample Output
310-1010 2
487-3279 4
888-4567 3

题意:所有字母转成相应数字,查一下有多少号码出现了不止一次,按字典序输出号码和出现次数。
用map来查重,用迭代器遍历。

#include<cstdio>
#include<iostream>
#include<map>
#include<cstring>
#define LL long longusing namespace std;
int n;
int l,sum,t;
int cal(char c)
{switch(c){case 'A':case 'B':case 'C': return 2;case 'D':case 'E':case 'F': return 3;case 'G':case 'H':case 'I': return 4;case 'J':case 'K':case 'L': return 5;case 'M':case 'N':case 'O': return 6;case 'P':case 'R':case 'S': return 7;case 'T':case 'U':case 'V': return 8;case 'W':case 'X':case 'Y': return 9;}
}int main()
{map<int,int>s;s.clear();
//  freopen("in.txt","r",stdin);cin>>n;while(n){char a[50];scanf("%s",a);int sum = 0;for(int i=0;i<strlen(a);i++){if(a[i]!='-'){if(a[i]>='A'&&a[i]<='Z'){sum = sum*10 + cal(a[i]); } else sum = sum*10 +(a[i] - '0');} s[sum]++;n--;} bool pd = false;for(map<int,int>::iterator i=s.begin();i!=s.end();i++)//迭代器访问map {if(i->second > 1){printf("%03d-%04d %d\n", i->first / 10000, i->first % 10000, i->second);//利用STL实现自动补上前导零 pd = true;}}if(pd==false) printf("No duplicates.\n");}

2.kmp算法

关于看xx算法 kmp算法的解析网上特别特别多,但各个博客中关于next数组第一位是0还是-1,数组从1开始还是从零开始规定都不太一样(就因为这个高一那会看这个算法的时候懵了整整一天 )。关于解析的话,我找了一个漫画解析感觉还不戳。

现规定在我的code中next数组第一个数值是-1,字符串数组从零开始计算。

点击进入漫画解析kmp

漫画直接copy过来了。

.

模板 & 例题1:luoguP3375 【模板】KMP字符串匹配

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char a[1000010],b[1000010];
int n,m,la,lb,t,N[1000010];
void next()//构造next数组
{N[0]=-1;int j = -1;for(int i=1;i<la;i++){while(b[i]!=b[j+1]&&j>-1){j = N[j];}if(b[i]==b[j+1]){j++;}N[i] = j;}
}
void kmp()//kmp本体
{int i=0,j=-1;while(i<=la){while(a[i]!=b[j+1]&&j>-1){ j = N[j];}if(a[i]==b[j+1]) {j++;if(j==lb-1){cout<<i-lb+2<<endl;j = N[j];}}i++;}
}
int main()
{scanf("%s %s",a,b);la = strlen(a);lb = strlen(b);next();kmp();for(int i=0;i<lb;i++){printf("%d ",N[i]+1);}return 0;
}

.
.
.

例题2

The Genographic Project is a research partnership between IBM and The National Geographic Society that is analyzing DNA from hundreds of thousands of contributors to map how the Earth was populated.

As an IBM researcher, you have been tasked with writing a program that will find commonalities amongst given snippets of DNA that can be correlated with individual survey information to identify new genetic markers.

A DNA base sequence is noted by listing the nitrogen bases in the order in which they are found in the molecule. There are four bases: adenine (A), thymine (T), guanine (G), and cytosine ©. A 6-base DNA sequence could be represented as TAGACC.

Given a set of DNA base sequences, determine the longest series of bases that occurs in all of the sequences.
Input
Input to this problem will begin with a line containing a single integer n indicating the number of datasets. Each dataset consists of the following components:
A single positive integer m (2 <= m <= 10) indicating the number of base sequences in this dataset.
m lines each containing a single base sequence consisting of 60 bases.
Output
For each dataset in the input, output the longest base subsequence common to all of the given base sequences. If the longest common subsequence is less than three bases in length, display the string “no significant commonalities” instead. If multiple subsequences of the same longest length exist, output only the subsequence that comes first in alphabetical order.

Sample Input

3
2
GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

3
GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA

GATACTAGATACTAGATACTAGATACTAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA

GATACCAGATACCAGATACCAGATACCAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA

3
CATCATCATCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC

ACATCATCATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AACATCATCATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

Sample Output
no significant commonalities
AGATAC
CATCATCAT

题意:查一下各组里各条链有没有三个及以上的重合部分。
idea:直接对第一条链各部分作为模式串kmp,但是!!考虑到不用查出现了几次和在哪里出现,所以可直接用STL函数解决(我们STL选手永不为奴 )(本shazi打完kmp才想起来还有个函数叫strsub )

STL函数版本:

s[j].find(ss)==string::npos//s中没有ss时候回返回一个npos
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#define LL long long
using namespace std;
string s[11],str,ss;
int main()
{int n,m;cin>>n;while(n){cin>>m;for(int i=1;i<=m;i++){cin>>s[i];}str = "no significant commonalities";for(int k=3;k<=60;k++){for(int i=0;i<=60-k;i++){bool pd = false;string ss = s[1].substr(i,k);for(int j=2;j<=m;j++){if(s[j].find(ss)==string::npos){pd = true;break;}}if(pd == false) {if(str == "no significant commonalities"){str = ss;}else if( str.size() < ss.size() ){str = ss;}else if( str.size() == ss.size() ){str = min( str,ss );}} }}cout<<str<<endl;n--;}return 0;
}

kmp版本

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#define LL long long
using namespace std;
string s[11],str,ss,a,b;
int la,lb,N[1000];
void next()
{N[0]=-1;int j = -1;for(int i=1;i<lb;i++){while(b[i] != b[j+1]&&j>-1){j = N[j];}if(b[j+1]==b[i]){j++;}N[i] = j;}
}
bool kmp()
{int i=0,j=-1;while(i<la){while(a[i]!=b[j+1]&&j>-1){j = N[j];}if(a[i]==b[j+1]) {j++;if(j==lb-1){return true;}}i++;}return false;
}
int main()
{//  freopen("in.txt","r",stdin);int n,m;cin>>n;while(n){cin>>m;for(int i=1;i<=m;i++){cin>>s[i];}str = "no significant commonalities";for(int k=3;k<=60;k++){for(int i=0;i<=60-k;i++){bool pd = false;b = s[1].substr(i,k);lb = b.size();next();for(int j=2;j<=m;j++){a = s[j];la = a.size();if( kmp() ==false ) {pd = true;break;}}if(pd == false) {if(str == "no significant commonalities"){str = b;}else if( str.size() < b.size() ){str = b;}else if( str.size() ==b.size() ){str = min( str,b );}} }}cout<<str<<endl;n--;}return 0;
}

例题3next数组的性质
It is well known that AekdyCoin is good at string problems as well as number theory problems. When given a string s, we can write down all the non-empty prefixes of this string. For example:
s: “abab”
The prefixes are: “a”, “ab”, “aba”, “abab”
For each prefix, we can count the times it matches in s. So we can see that prefix “a” matches twice, “ab” matches twice too, “aba” matches once, and “abab” matches once. Now you are asked to calculate the sum of the match times for all the prefixes. For “abab”, it is 2 + 2 + 1 + 1 = 6.
The answer may be very large, so output the answer mod 10007.
Input
The first line is a single integer T, indicating the number of test cases.
For each case, the first line is an integer n (1 <= n <= 200000), which is the length of string s. A line follows giving the string s. The characters in the strings are all lower-case letters.
Output
For each case, output only one number: the sum of the match times for all the prefixes of s mod 10007.
Sample Input
1
4
abab
Sample Output
6

题意:给T组数据,每组数据给一个长度为n的字符串s。求字符串每个前缀出现的次数和,结果mod 10007。
idea:利用kmp算法的next数组可以很好的解决这个问题, next数组存放的是字符串的前缀和后缀能匹配的字符个数的最大值。

对于i,(1 <= i <=n),n是字符串s的长度

    如果next[i]  == -1 则表示   由s的前i个字符组成的字符串的所有后缀肯定和其前缀不匹配。否则      由s的前i个字符组成的字符串存在某个前缀和后缀匹配的情况,也就是该前缀的出现的次数应该加上1。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int qwq = 10007;
char a[200100],b[200100];
int N[200100],la,lb,ans=0;
void Getnext()
{N[0] = -1;int j =-1;for(int i=1;i<lb;i++){while(b[i]!=b[j+1]&&j>-1){j = N[j];}if(b[i]==b[j+1]){j++;}N[i] = j;}
}
void kmp()
{int i=0,j=-1;while(i<la){while(a[i]!=b[j+1]&&j>-1){j = N[j];}if(a[i]==b[j+1]){j++;if(j==lb-1){j = N[j];ans++;ans %= qwq;}}i++;}
}
int main()
{int n,m;cin>>n;while(n){ans = 0;cin>>m;scanf("%s",a);strcpy(b,a);la = m;lb = m;Getnext();int t = lb;
//      for(int i=0;i<m;i++) cout<<N[i]<<" ";
//      kmp();for(int i=0;i<lb;i++){if(N[i]!=-1) ans++;ans %=qwq;}cout<<(ans+m)%qwq<<endl;n--;}return 0;
}

例题4


 题意:给你两个串只有0和1的T,S,其中S可以进行循环右移,问你S里面是否存在两个长度都为|S|的子串它们的异或结果等于T。
 
idea:根据xor的性质,可以先把T和S→移动过的一个串进行XOR,再到S右移的子串中查询。刚开始我XOR完居然去和T匹配,改到人傻了 。

直接把两个S拼起来就可以取到任意移动过的串了

#pragma GCC optimize(2)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define M 1000002
#define XOR(x,y) ( x==y ? '0' : '1')
using namespace std;
char s[M],t[M],b[M];
int N[M],ls,lt,lss;
bool pd;
void Getnext()
{//  memset(N,-1,sizeof(N));N[0]=-1;int j = -1;for(int i=1;i<lt;i++){while(b[i]!=b[j+1]&&j>-1){j = N[j];}if(b[i]==b[j+1]){j++;}N[i] = j;}
}
bool kmp(int f)
{for(int k=0;k<lt;k++){b[k] = XOR( t[k],s[f+k] );}Getnext();int i=0,j=-1;while(i<=lss){while(s[i]!=b[j+1]&&j>-1){j = N[j];}if(s[i]==b[j+1]){j++;if(j==lt-1){return true;}}i++;}return false;
}
int main()
{//  freopen("in.txt","r",stdin);while( scanf("%s %s",t,s)!=EOF ){pd = false;ls = strlen(s);lt = strlen(t);lss = 2*ls;s[ls*2]='\0';for(int i=0;i<ls;i++){s[ls+i] = s[i];}for(int i=0;i<ls;i++){pd = kmp(i);if(pd==true) break;}if(pd==true) printf("Yes\n");else printf("No\n");}return 0;
}

.
.
.

3.manacher算法

推荐马拉车算法一个还不错的教程

manacher算法是用来处理回文字符串问题一个线性算法,时间复杂度为O(n)。

回文串的个数是可奇可偶的,碰上奇数的回文串还可以,如果是偶数的回文串没有着脚点,那就很恼人了。所以马拉车算法会对字符串进行预先处理,然后再求最长的回文串。首先用字符串中没有出现过的字符来表示串中每个元素的间隔,而为了防止在访问时出现越界情况,需要在串首和串尾再加上额外的特殊字符。

例如:原串为ababab;处理完之后就是#a#b#a#b#a#b#; 其实对于最后一个$,也可以不加,因为字符串的最后一个字符是‘\0’就相当于一个特殊字符了。
2、接下来就是在新串中找以每一个字符为中心的回文串就可以了。manacher算法的思想就是从左到右求出以每个字符为中心的最长回文串。设能延伸到最右边的字符串的中心位置为id,该字符串最右端的位置为mx,pal数组来储存此处回文串的长度。因为回文串有对称的性质,所以后边的字符串可以通过对称来直接求得其长度(当然前边的还是需要乖乖的遍历求出来的)。

3、对于遍历到的字符(下标设为i),一共会有三种情况;

(1)i<=mx;

该情况下就万事大吉了,直接把2*id-i处串的长度,复制给i就OK了。

(2)i<=mx
同样是这种情况但是出现i处的回文串超出了mx的情况

最右端超出了mx的范围,出现什么情况就不好说了,所以只能暴力一下,然后更新mx的大小就可以了

(3)i>mx
这种情况直接暴力,求此处回文串的长度即可。

模板&例题 luoguP3805 【模板】manacher算法

 #include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
#define N 11000100
using namespace std;
char a[N],ch[2*N+10];
int mx,p[2*N+10],sum=0,ans=0,len,pos=0;
void manacher()
{for(int i=1;i<=2*len+1;i++){int j;if(i<mx){j = 2*pos-i;p[i] = min( p[j] , mx-i );}else{if(ch[i]=='#') p[i] = 1;else p[i] = 2;}while( ch[ i-p[i] ] == ch[ i+p[i] ] ) p[i]++;//向两侧扩展,找最大。if(i+p[i]-1 > mx){mx = i+p[i]-1;pos = i;}ans = max(ans,p[i]-1);}
}
int main()
{scanf("%s",a+1);len = strlen(a+1);ch[0] = '@';ch[2*len + 2] = '&';for(int i=1;i<=2*len+1;i++){if(i%2==1){ch[i] = '#';}else{ch[i] = a[i/2];}}manacher();cout<<ans;return 0;
}

.
.
.

4.拓展KMP(Z函数)

拓展kmp极佳讲解

例题导入

证明部分的我是搬运工




if(i+nxt[i-p0]<extend[p0]+p0)extend[i]=nxt[i-p0];
//i相当于k+1
//nxt[i-p0]相当于L
//extend[p0]+p0相当于p
//因为在代码里我是从0开始记字符串的,所以本应在小于号左侧减1,现在不用了。

int now=extend[p0]+p0-i;
now=max(now,0);//这里是防止i>p
while(t[now]==s[i+now]&&now<(int)t.size()&&now+i<(int)s.size())now++;//暴力求解的过程
extend[i]=now;
p0=i;//更新p0


总的代码:

#include<bits/stdc++.h>#define N 1000010 using namespace std;int q,nxt[N],extend[N];
string s,t;void getnxt()
{nxt[0]=t.size();//nxt[0]一定是T的长度int now=0;while(t[now]==t[1+now]&&now+1<(int)t.size())now++;//这就是从1开始暴力nxt[1]=now;int p0=1;for(int i=2;i<(int)t.size();i++){if(i+nxt[i-p0]<nxt[p0]+p0)nxt[i]=nxt[i-p0];//第一种情况else{//第二种情况int now=nxt[p0]+p0-i;now=max(now,0);//这里是为了防止i>p的情况while(t[now]==t[i+now]&&i+now<(int)t.size())now++;//暴力nxt[i]=now;p0=i;//更新p0}}
}void exkmp()
{getnxt();int now=0;while(s[now]==t[now]&&now<min((int)s.size(),(int)t.size()))now++;//暴力extend[0]=now;int p0=0;for(int i=1;i<(int)s.size();i++){if(i+nxt[i-p0]<extend[p0]+p0)extend[i]=nxt[i-p0];//第一种情况else{//第二种情况int now=extend[p0]+p0-i;now=max(now,0);//这里是为了防止i>p的情况while(t[now]==s[i+now]&&now<(int)t.size()&&now+i<(int)s.size())now++;//暴力extend[i]=now;p0=i;//更新p0}}
}int main()
{cin>>s>>t;exkmp();int len=t.size();for(int i=0;i<len;i++)printf("%d ",nxt[i]);//输出nxtputs("");len=s.size();for(int i=0;i<len;i++)printf("%d ",extend[i]);//输出extendreturn 0;
}

.
.
.

5.AC自动机&&tire树

当年GDKOI就被这玩意干翻过----蒟蒻如是说道
这部分让我手敲解析不如neng si我算了
直接呈上dalao讲解

老模板题了


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
char txt[1000005],ch[160][80];
int cishu[160],num=0,maxn,n;
struct node
{int son[30],fail,x,cot;bool have;
}trie[20005];
void re()
{num=0;maxn=0;memset(trie,0,sizeof(trie));memset(cishu,0,sizeof(cishu));trie[0].fail=-1;
}
void insert(int j)
{int len=strlen(ch[j]);int a=0,b;for(int i=0;i<len;i++){b=ch[j][i]-'a';if(!trie[a].son[b]) trie[a].son[b]=++num;a=trie[a].son[b];}trie[a].have=1;trie[a].x=j;
}
void getfail()
{queue<int>dui;dui.push(0);int a;while(!dui.empty()){a=dui.front();dui.pop();for(int i=0;i<26;i++){if(trie[a].son[i]){if(a==0){trie[trie[a].son[i]].fail=0;}else {int p=trie[a].fail;while(p!=-1){if(trie[p].son[i]){trie[trie[a].son[i]].fail=trie[p].son[i];break;}p=trie[p].fail;}if(p==-1){trie[trie[a].son[i]].fail=0;}}dui.push(trie[a].son[i]);}}}
}
void pp()
{int len=strlen(txt);int a=0,b;for(int i=0;i<len;i++){b=txt[i]-'a';while(a!=0&&trie[a].son[b]==0){a=trie[a].fail;}if(trie[a].son[b])a=trie[a].son[b];int p=a;while(p!=0){if(trie[p].have){++cishu[trie[p].x];maxn=max(maxn,cishu[trie[p].x]);}p=trie[p].fail;}}
}
int main()
{//freopen("hh.txt","r",stdin);while(scanf("%d",&n)){if(!n){return 0;}re();for(int i=1;i<=n;i++){scanf("%s",&ch[i]);insert(i);}getfail();cin>>txt;pp();cout<<maxn<<endl;for(int i=1;i<=n;i++){if(cishu[i]==maxn){printf("%s\n",ch[i]);}}}return 0;
}

还是一条不存在的分割线

写在后面:
刚好今天是NOIP复赛日,不禁让我回想起来2018年那一场NOIP,当时高三的我为了这场比赛翘了一个月晚修在机房训练,只为弥补高二那年初赛因为一些意外无法参加无缘复赛的遗憾。最后的结果也算是对得起从高一才开始学OI的我两年的OI生涯了。

week5小结(字符串类)相关推荐

  1. C++实验6 改造实验5中的Player类、自行设计字符串类

    [实验名称]数组.指针与字符串 [实验目的] 1.练习观察指针的内容及其所指的对象的内容 2.通过动态内存分配实现数组,并体会指针在其中的作用. 3.使用字符数组练习处理字符串的方法. [实验原理] ...

  2. C++ 笔记(19)— 标准模板库(STL容器、STL迭代器、STL算法、STL容器特点、STL字符串类)

    C++ 标准库可以分为两部分: 标准函数库: 这个库是由通用的.独立的.不属于任何类的函数组成的.函数库继承自 C 语言. 面向对象类库: 这个库是类及其相关函数的集合. C++ 标准库包含了所有的 ...

  3. php如何一篇文章替换敏感字,php实现的替换敏感字符串类实例

    本文实例讲述了php实现的替换敏感字符串类及其用法,在php程序开发中有着非常广泛的应用价值.分享给大家供大家参考.具体方法如下: StrFilter.class.php类文件如下: _white_l ...

  4. Java:字符串类String的功能介绍

    在java中,字符串是一个比较常用的类,因为代码中基本上处理的很多数据都是字符串类型的,因此,掌握字符串类的具体用法显得很重要了. 它的主要功能有如下几种:获取.判断.转换.替换.切割.字串的获取.大 ...

  5. 字符串类String

    文章目录 1 字符串类的初步设计 1.1 历史遗留问题 1.2 字符串类的初步设计 1.3 代码实现 2 字符串类功能的进一步实现 2.1 重载数组访问操作符[] 2.2 判断是否以指定字符串开始或结 ...

  6. string 字符串中字符无效_7.3 C++字符串类 | 使用string输出

    C++字符串类 C++提供了一种新的数据类型:字符串类型,它和char,int类型一样,可以用来定义变量,用一个名字代表一个字符序列,这就是字符串变量. 读者需要明白string并不是C++本身具有的 ...

  7. 3.vector实现字符串类

    3.vector实现字符串类 本章前言: 身为土生土长的中国程序员,你肯定要用unicode来编写程序.但是由wchar_t数组实现的字符串准确点说应该叫字符数组,但它在使用时比较繁琐,而且容易出现数 ...

  8. QT学习:字符串类QString

    标准C++提供了两种字符串:一种是c语言风格的以"\0"字符结尾的字符数组:另一种是字符串类String.而Qt字符串类QString的功能更强大. QString类保存16位Un ...

  9. DCMTK:C ++字符串类OFString的测试程序

    DCMTK:C ++字符串类OFString的测试程序 C ++字符串类OFString的测试程序 C ++字符串类OFString的测试程序 #include "dcmtk/config/ ...

  10. C++字符串完全指南(2) - 各种字符串类- CRT类

    C++字符串完全指南(2) - 各种字符串类- CRT类 _bstr_t 字符串包装类 我已经说明了字符串的各种类型,现在讨论包装类.对于每个包装类,我都会说明它的对象构造过程和如何转换成C类型字符串 ...

最新文章

  1. 记录一个在线压缩和还原压缩js代码的工具
  2. 文献记录(part4)--Sparse Biclustering of Transposable Data
  3. 使用onclick跳转到其他页面。使用button跳转到指定url
  4. ML.NET 示例:将ML.NET模型导出到ONNX
  5. Apache Spark软件包,从XML到JSON
  6. 单片机与gsm通信c语言,gsm模块如何与单片机通信?
  7. 待人真诚p2psearcher2013源码下载
  8. 软件测试笔试Linux题,linux基础面试题
  9. Span中显示内容过长显示省略号---SpringCloud Alibaba_若依微服务框架改造_前端基于Vue的ElementUI---工作笔记011
  10. python画出roc曲线 auc计算逻辑_从scikitlearn(sklearn)的多类数据计算AUC和ROC曲线?...
  11. 智迈职称计算机一练通破解版,智迈初级会计职称考试软件
  12. 如何在简历中编写Spark大数据项目经验
  13. 洛谷 P1957 口算练习题 题解 字符串 C/C++
  14. CI/CD 流程以及原理
  15. Rational License Key Error的解决办法
  16. 来啊battle啊,Java和Python你站哪个?
  17. 局部敏感哈希(Locality-Sensitive Hashing, LSH)
  18. Fliqlo时钟屏保Windows版本
  19. 使用bug分类来设计更好的软件测试
  20. 某金融机构身份国产化LDAP创新实践——国产自主可控 LDAP目录服务建设经验分享

热门文章

  1. Java爬虫的简易实现,爬取深度可控
  2. Python:使用Selenium和requests爬取文章
  3. Quick Charge技术解析:关于手机快速充电的那些事儿
  4. 从零开始的Python计划#8.2 继承
  5. 三国争霸 Linux三款音乐播放器全方位PK
  6. 广义平稳随机过程定义_广义平稳随机信号,wide-sense stationary random signals,音标,读音,翻译,英文例句,英语词典...
  7. 公式编辑器中如何加粗部分变量Ps:如向量。
  8. 【JAVASE系列】四大内部类
  9. 笔记-商务与经济统计 第2章 描述统计学 I:表格法和图形法
  10. Error creating bean with name 'sqlSessionFactory' defined in class path resource