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

相关文章

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

分布式系统的个人理解小结

分布式系统:分的微小服务,以小而独立的业务为单位,形成子系统。 然后分布式系统中需要有统一的调用,形成大的聚合服务。 同时,微服务群,需要有交流(通讯,注册中心,同步,异步),有管理(监控,调度)。 对外服务,需要有控制的对外开发,安全网关。

C和指针:字符串

字符串、字符和字节 字符串基础 字符串就是一串零个或多个字符,并且以一个位模式为全0的NUL字节结尾。 字符串长度就是字符串中字符数。 size_t strlen( char const *string ); string为指针常量(const修饰string),指向的string是常量不能修改。size_t是无符号数,定义在stddef.h。 #include <stddef.h>

PHP字符串全排列

方法一: $str = 'abc';$a =str_split($str);perm($a, 0, count($a)-1);function perm(&$ar, $k, $m) {if($k == $m){ echo join('',$ar), PHP_EOL;}else {for($i=$k; $i<=$m; $i++) {swap($ar[$k], $ar[$i]);perm($ar

PHP7扩展开发之字符串处理

前言 这次,我们来看看字符串在PHP扩展里面如何处理。 示例代码如下: <?phpfunction str_concat($prefix, $string) {$len = strlen($prefix);$substr = substr($string, 0, $len);if ($substr != $prefix) {return $prefix." ".$string;} else

十一、C语言:字符串函数

目录 一、strlen 二、strcpy 三、strcat  四、strcmp 五、strstr 六、strtok 七、strerror 一、strlen 注意:strlen()函数的返回值是size_t,两个size_t相减仍为无符号数 int main(){char arr[10] = "abc";char brr[10] = "abc123";if (strl

NC 把数字翻译成字符串

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 描述 有一种将字母编码成数字的方式:‘a’->1, ‘b->2’, … , ‘z->26’。 现在给一串数字,返回有多少种可能的译码结果 import java.u

C语言进阶【1】--字符函数和字符串函数【1】

本章概述 字符分类函数字符转换函数strlen的使用和模拟实现strcpy的使用和模拟实现strcat的使用和模拟实现strcmp的使用和模拟实现彩蛋时刻!!! 字符分类函数 字符: 这个概念,我们在以前的文章中讲过了。我们键盘输入的信息都是字符。字符大体可以分为两类——单个字符,字符串。而单个字符又可以进行分类——字母字符,数字字符,特殊字符和不可见字符。进行思维图展示: 在日

nyoj 685 查找字符串

当初一开始没做出来。 后来,学习过一段时间之后,在返回来做这道题,忽然发现,map类容器可以做。 PS:需要注意的是:此题如果用c++的输入输出的话,会超时。 O(time):gets()<  scanf() < cin。   附上代码: #include<stdio.h>#include<map>#include<string>#include<string.h>usin

shell脚本中变量中字符串替换的测试 /和//的区别

test_char=abbbcbbbf echo "bf:test_char = " $test_char test_char=${test_char/bbb/ddd} echo "af:test_char = " $test_char 输出: bf:test_char =  abbbcbbbf af:test_char =  adddcbbbf 只匹配第一个