xxxx
7-1 【模板】KMP字符串匹配 (20 分)
点击查看代码
给出两个字符串text和pattern,其中pattern为text的子串,求出pattern在text中所有出现的位置。为了减少骗分的情况,接下来还要输出子串的前缀数组next。
输入格式:
第一行为一个字符串,即为text。
第二行为一个字符串,即为pattern。
输出格式:
若干行,每行包含一个整数,表示pattern在text中出现的位置。
接下来1行,包括length(pattern)个整数,表示前缀数组next[i]的值,数据间以一个空格分隔,行尾无多余空格。
输入样例:
ABABABC
ABA
结尾无空行
输出样例:
1
3
0 0 1
#include<bits/stdc++.h>
using namespace std;
string text;
string pattern;
long long nex[100000];
int outne[100000];
int len;
int n;
void getnext()
{
nex[0]=-1;
int plen=0;
int i=1;
outne[0]=0;
while(i<n)
{
if(pattern[i]==pattern[plen])
{
plen++;
outne[i]=plen;
i++;
}
else
{
if(plen>0)
{
plen= outne[plen-1];
}
else
{
outne[i]=plen;
i++;
}
}
}
nex[0]=-1;
for(i=0;i<n;i++)
{
nex[i+1]=outne[i];
}
}
void indexkmp()
{
getnext();
int i=0;
int j=0;
while(i<len)
{
if(j==n-1&&text[i]==pattern[j])
{
cout<<i-j+1<<endl;
// i=i-j+1;
j=nex[j];
}
if(j==-1||text[i]==pattern[j])
{
i++;
j++;
}
else
{
j=nex[j];
}
}
}
int main()
{
cin>>text;
cin>>pattern;
len=text.length();
n=pattern.length();
indexkmp();
for(int i=0;i<n;i++)
{
if(i==n-1)
cout<<outne[i]<<endl;
else
cout<<outne[i]<<" ";
}
return 0;
}
7-2 串的模式匹配 (25 分)
点击查看代码
给定两个由英文字母组成的字符串 String 和 Pattern,要求找到 Pattern 在 String 中第一次出现的位置,并将此位置后的 String 的子串输出。如果找不到,则输出“Not Found”。
本题旨在测试各种不同的匹配算法在各种数据情况下的表现。各组测试数据特点如下:
数据0:小规模字符串,测试基本正确性;
数据1:随机数据,String 长度为 10
5
,Pattern 长度为 10;
数据2:随机数据,String 长度为 10
5
,Pattern 长度为 10
2
;
数据3:随机数据,String 长度为 10
5
,Pattern 长度为 10
3
;
数据4:随机数据,String 长度为 10
5
,Pattern 长度为 10
4
;
数据5:String 长度为 10
6
,Pattern 长度为 10
5
;测试尾字符不匹配的情形;
数据6:String 长度为 10
6
,Pattern 长度为 10
5
;测试首字符不匹配的情形。
输入格式:
输入第一行给出 String,为由英文字母组成的、长度不超过 10
6
的字符串。第二行给出一个正整数 N(≤10),为待匹配的模式串的个数。随后 N 行,每行给出一个 Pattern,为由英文字母组成的、长度不超过 10
5
的字符串。每个字符串都非空,以回车结束。
输出格式:
对每个 Pattern,按照题面要求输出匹配结果。
输入样例:
abcabcabcabcacabxy
3
abcabcacab
cabcabcd
abcabcabcabcacabxyz
结尾无空行
输出样例:
abcabcacabxy
Not Found
Not Found
#include<bits/stdc++.h>
using namespace std;
string S;
string T;
int slen;
int tlen;
int nex[1100000];
void getnext()
{
int pre=-1;
nex[0]=-1;
int j=0;
while(j<tlen)
{
if(pre==-1||T[pre]==T[j])
{
j++;
pre++;
nex[j]=pre;
}
else pre=nex[pre];
}
/* for( j=0;j<tlen;j++)
{
cout<<nex[j];
}*/
}
void index_KMP()
{
getnext();
int i=0;
int j=0;
while(i<slen)
{
if(j==tlen-1&&S[i]==T[j])
{
for(i-=j;i<slen;i++)
{
cout<<S[i];
}
return;
}
if(j==-1||S[i]==T[j])
{
i++;
j++;
}
else
{
j=nex[j];
}
}
cout<<"Not Found";
}
int main()
{
cin>>S;
slen=S.length();
int n;
cin>>n;
for( int i=0;i<n;i++)
{
cin>>T;
tlen=T.length();
index_KMP();
cout<<endl;
}
return 0;
}
7-3 字符串模式匹配 (5 分)
点击查看代码
给定主串s和模式串p,编写程序输出p在s中出现的首位置,若p不在s中则输出-1。字符串下标从0开始。输入格式:
输入为2行,第1行主串s,第2行为模式串p。主串和模式串长度不超过100000。
输出格式:
输出为2行,第1行为若干整数,表示模式串p的失败函数值,每个整数后一个空格;第2行为一个整数,表示p在s中出现的首位置,若p不在s中则输出-1。
输入样例:
qwerabcabhlk
abcab
输出样例:
-1 -1 -1 0 1
4
#include<bits/stdc++.h>
using namespace std;
string S;
string T;
int slen;
int tlen;
void getnext(int next[])
{
int pre=0;
next[0]=0;
int j=1;
while(j<tlen)
{
if(T[pre]==T[j])
{
pre++;
next[j]=pre;
j++;
}
else
{
if(pre>0)
pre=next[pre-1];
else
{
next[j]=pre;
j++;
}
}
}
for(int i=0;i<tlen;i++)
{
if(i==tlen-1)
{
cout<<next[i]-1<<" "<<endl;
}
else{
cout<<next[i]-1<<" ";
}
}
for(int i=tlen-1;i>0;i--)
{
next[i+1]=next[i];
}
next[0]=-1;
}
void indexkmp()
{
int next[10000];
getnext(next);
int i=0;
int j=0;
while(i<slen)
{
if(j==tlen-1&&S[i]==T[j])
{
cout<<i-j<<endl;
return;
}
if(j==-1||S[i]==T[j])
{
i++;
j++;
}
else
{
j=next[j];
}
}
cout<<-1<<endl;
}
int main()
{
cin>>S>>T;
slen=S.length();
tlen=T.length();
indexkmp();
return 0;
}
好中缀
点击查看代码
我们称一个字符串S的子串T为好中缀,如果T是去除S中满足如下条件的两个子串p和q后剩余的字符串。(1)p是S的前缀,q是S的后缀;
(2)p=q;
(3)p和q是满足条件(1)(2)的所有子串中的第二长者。
注意一个字符串不能称为自己的前缀或后缀。好中缀至少为空串,其长度大于等于0,不能为负数。
输入格式:
输入为一个字符串S,包含不超过100000个字母。
输出格式:
输出为一个整数,表示好中缀的长度。
输入样例1:
abcabcxxxabcabc
输出样例1:
9
输入样例2:
xacbacba
输出样例2:
8
输入样例3:
aaa
输出样例3:
1
#include<bits/stdc++.h>
using namespace std;
string s;
int nnex[100100];
int ans[100100];
void getnext(int n)
{
nnex[0]=-1;
int pre=-1;
int j=0;
while(j<n)
{
if(pre==-1||s[pre]==s[j])
{
pre++;
j++;
nnex[j]=pre;
}
else
{
pre=nnex[pre];
}
}
}
int main()
{
cin>>s;
getnext(s.length());
int len=s.length();
int j=nnex[len];
int c=0;
int cnt=0;
while(j>0)
{
ans[c++]=j;
j=nnex[j];
}
sort(ans,ans+len,greater<int>());
int x=len-ans[1]*2;
if(x<0) x=0;
cout<<x<<endl;
return 0;
}
7-5 三元组顺序表表示的稀疏矩阵转置Ⅱ (10 分)
点击查看题目
三元组顺序表表示的稀疏矩阵转置Ⅱ。设a和b为三元组顺序表变量,分别表示矩阵M和T。要求按照a中三元组的次序进行转置,并将转置后的三元组置入b中恰当的位置。
输入格式:
输入第1行为矩阵行数m、列数n及非零元素个数t。 按行优先顺序依次输入t行,每行3个数,分别表示非零元素的行标、列标和值。
输出格式:
按置入b中的顺序输出置入的位置下标,转置后的三元组行标、列标和值,数据之间用空格分隔,共t行。
输入样例1:
3 4 3
0 1 -5
1 0 1
2 2 2
结尾无空行
输出样例1:
1 1 0 -5
0 0 1 1
2 2 2 2
#include<stdio.h>
typedef struct {
int p,i, j;
int data;
}triple;
typedef struct {
triple data[10];
int n, m, num;
}TSMATRIX;
TSMATRIX ChangeMatr(TSMATRIX M, TSMATRIX T) {
T.m = M.n;
T.n = M.m;
T.num = M.num;
if (T.num) {
int q = 0;
int col;
for (col = 0; col <= M.m; ++col) {
int p;
for (p = 0; p < M.num; ++p) {
if (M.data[p].j == col) {
T.data[q].i = M.data[p].j;
T.data[q].j = M.data[p].i;
T.data[q].data = M.data[p].data;
q++;
}
}
}
}
return T;
}
int main() {
TSMATRIX M;
int k=0;
scanf("%d %d %d",&M.m,&M.n,&M.num);
while(k!=M.num){
scanf("%d %d %d",&M.data[k].i,&M.data[k].j,&M.data[k].data);
k++;
}
TSMATRIX T;
int k1;
for (k1 = 0; k1 <=M.num; k1++) {
T.data[k1].i = 0;
T.data[k1].j = 0;
T.data[k1].data = 0;
}
T = ChangeMatr(M, T);
int i;
for (i = 0; i < T.num; i++) {
T.data[i].p = i;
}
for (i = 0; i < T.num; i++) {
int j;
int k = M.data[i].data;
for(j = 0; j < T.num; j++){
if(T.data[j].data == k){
printf((i+1 == T.num) ? "%d %d %d %d":"%d %d %d %d\n", T.data[j].p, T.data[j].i, T.data[j].j, T.data[j].data);
}
}
}
return 0;
}