week5小结(字符串类)

2023-11-08 13:40
文章标签 字符串 小结 week5

本文主要是介绍week5小结(字符串类),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

碰巧今天是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小结(字符串类)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/370239

相关文章

Spring Cloud Hystrix原理与注意事项小结

《SpringCloudHystrix原理与注意事项小结》本文介绍了Hystrix的基本概念、工作原理以及其在实际开发中的应用方式,通过对Hystrix的深入学习,开发者可以在分布式系统中实现精细... 目录一、Spring Cloud Hystrix概述和设计目标(一)Spring Cloud Hystr

Keepalived+Nginx双机配置小结

《Keepalived+Nginx双机配置小结》本文主要介绍了Keepalived+Nginx双机配置小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1.1 软硬件要求1.2 部署前服务器配置调优1.3 Nginx+Keepalived部署1.3

nginx upstream六种方式分配小结

《nginxupstream六种方式分配小结》本文主要介绍了nginxupstream六种方式分配小结,包括轮询、加权轮询、IP哈希、公平轮询、URL哈希和备份服务器,具有一定的参考价格,感兴趣的可... 目录1 轮询(默认)2 weight3 ip_hash4 fair(第三方)5 url_hash(第三

Python中conda虚拟环境创建及使用小结

《Python中conda虚拟环境创建及使用小结》本文主要介绍了Python中conda虚拟环境创建及使用小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录0.前言1.Miniconda安装2.conda本地基本操作3.创建conda虚拟环境4.激活c

Java对象和JSON字符串之间的转换方法(全网最清晰)

《Java对象和JSON字符串之间的转换方法(全网最清晰)》:本文主要介绍如何在Java中使用Jackson库将对象转换为JSON字符串,并提供了一个简单的工具类示例,该工具类支持基本的转换功能,... 目录前言1. 引入 Jackson 依赖2. 创建 jsON 工具类3. 使用示例转换 Java 对象为

MobaXterm远程登录工具功能与应用小结

《MobaXterm远程登录工具功能与应用小结》MobaXterm是一款功能强大的远程终端软件,主要支持SSH登录,拥有多种远程协议,实现跨平台访问,它包括多会话管理、本地命令行执行、图形化界面集成和... 目录1. 远程终端软件概述1.1 远程终端软件的定义与用途1.2 远程终端软件的关键特性2. 支持的

golang字符串匹配算法解读

《golang字符串匹配算法解读》文章介绍了字符串匹配算法的原理,特别是Knuth-Morris-Pratt(KMP)算法,该算法通过构建模式串的前缀表来减少匹配时的不必要的字符比较,从而提高效率,在... 目录简介KMP实现代码总结简介字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串(称为

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui