目录
补发一下,原来忘记发了。
1.等值字串
【问题描述】如果字符串的一个子串(其长度大于1)的各个字符均相同,则称之为等值子串。试设计一算法,求出串S中一个长度最大的等值子串;如果串S 中不存在等值子串,则输出信息no
【输入形式】输入一个字符串,并以!结束
【输出形式】输出第一个出现的最长字符串,如果没有输出no
【样例输入】aabc123abc123cc!
【样例输出】aa
【样例输入】abceebccadddddaaadd!
【样例输出】ddddd
#include<bits/stdc++.h>
using namespace std;
int main(){
string c;
cin >> c;
int s = 0, num = 0, stemp = 0, a = 1;
int len = c.length();
for(int i = 1; i < len; i++){
if(c[i] == c[i - 1]) a++;
else {
if(a > num) {
num = a;
s = stemp;
}
stemp = i;
a = 1;
}
}
if(num > 1)
for(int i = s; i < s + num; i++){
cout << c[i];
}
else cout << "no";
}
2.KMP匹配
【问题描述】KMP算法是字符串模式匹配算法中较为高效的算法之一,其在某次子串匹配母串失败时并未回溯母串的指针而是将子串的指针移动到相应的位置。
【输入形式】3组字符串,每组字符串占一行。每行包含由空格分隔的两个字符串,字符串仅由英文小写字母组成且长度不大于100。
【输出形式】每组数据输出1行,输出后一个字符串在前一个字符串中的位置,如果不匹配,则输出0。
【样例输入】
string str
thisisalongstring isa
nosubstring subt【样例输出】
1
5
0
【提示】表示字符串的数据结构可以是字符数组或用串类实现。KMP算法调用很简单,但难的是理解算法的思想。掌握算法的思想才能说是掌握算法。
#include<bits/stdc++.h>
#define M 2000
using namespace std;
/*typedef struct
{
char ch[ M ];
int len;
}SString;*/
//int next[ M ] ;
int KMP( string T , string P, int next[] ,int len1 , int len2 )
{
int i = 0 , j = 0;
while( i < len1 && j < len2 )
{
if( j == -1)
{
i++;
j=0;
}
else if( P[j] == T[i] )
{
i++;
j++;
}
else j = next[ j ];
}
if( j < len2 )
return -1;
else return i-j;
}
/*void getNext( string P , int next[] ,int len2 )
{
next[ 0 ] = -1;
int j = 0, k = -1;
while( j < len2 -1 )
{
if( k == -1)
{
next[ j + 1 ] = 0;
j++;
k=0;
}
else if( P[ k ] == P[ j ] )
{
next[ j + 1 ] = k + 1;
j++;
k++;
}
else
{
k = next[ k ];
}
}
}*/
int main()
{
int m=0;
int next[ M ] ;
string T ;
string P ;
while( cin >> T >> P )
{ int len1 = T.size();
int len2 = P.size();
//getNext( P, next ,len2 );
next[ 0 ] = -1;
int j = 0, k = -1;
while( j < len2 -1 )
{
if( k == -1)
{
next[ j + 1 ] = 0;
j++;
k=0;
}
else if( P[ k ] == P[ j ] )
{
next[ j + 1 ] = k + 1;
j++;
k++;
}
else
{
k = next[ k ];
}
}
m=KMP( T , P, next ,len1 , len2 );
if(m != -1)
cout << m+1 << endl;
else
cout<< "0" <<endl;
}
}
3.大整数相乘
【问题描述】输出两个不超过100位的大整数的乘积。
要求用串这一章的“块链串”知识实现两个大整数的相乘。比如每一个结点存储5位,12345678983426801则需要4个结点;先实现大整数乘上一个一位数;再实现两个大数相加。
用这样的链式存储形式便于计算:12--->34567--->89834--->26801
或者:26801--->89834--->34567--->12
【输入形式】
两个大数
【输出形式】
相乘的结果
【样例输入】
1234567891011121314151617181920
2019181716151413121110987654321
【样例输出】
2492816912877266687794240983772975935013386905490061131076320
#include <bits/stdc++.h>
using namespace std;
int arr[210];//接收结果的一个数组
typedef struct Link//块链串
{
int Maxsize ;
int num[5];
struct Link*next;
}Link;
Link * Init ( Link *p , char s[] )//初始化块链串
{
Link *head = p;
for(int i = 0 ; s[i] != '\0' ; i++)
{
if(i != 0 && i%5 == 0)
{
p -> next = new Link;
p = p -> next;
}
p -> num [i % 5] = s[i] -'0';
p -> Maxsize = i % 5 ;
}
p -> next = NULL;
return head;
}
void multiplication(Link *head1 , Link *head2 )//大整数乘法
{
Link *p,*q;
int N = 0, M = 0 , i , j , Max = 0,m;
//N,M记录偏移值
//M处理第一个串的不同节点之间的相加时的定位
//N处理另一个串
//Max是当前最大长度
for( p = head1 ; p != NULL ; p = p -> next )//遍历a
{
if(p != head1)
N+=5;
for( i = 0; i <= p -> Maxsize ; i++ )//实现两个大整数的每一位相乘
{
for( q = head2 ; q != NULL ; q = q -> next )
{
if( q != head2 )
M+=5;
for( j = 0 ; j <= q -> Maxsize ; j++)
{
m = M + N + i + j + 1;
arr[ m ] += q -> num [ j ] * p -> num[ i ];
//cout<<i<<" "<<j<<" "<<m<<endl;
Max = Max>m? Max :m;
}
}
M=0;
}
}
for( int k = Max ; k > 0 ; k-- )//进位问题
{
if( arr [ k ] >= 10 )
{
arr [ k - 1 ] += arr[ k ]/10;
arr[ k ] %= 10;
}
}
int k=0;
if(arr [ k ] == 0)
k++;
for(; k <= Max ; k++)
cout<<arr [ k ];
cout<<endl;
}
int main()
{
char a[100] , b[100];
cin >> a >> b ;
Link*head1,*head2;
head1 = new Link;
head2 = new Link;
head1 = Init ( head1 , a );
head2 = Init ( head2 , b );
multiplication( head1 , head2 );
}
4.最长公共子串
【问题描述】
给定两个字符串,求出它们两个最长的相同子字符串的长度。
最长公共子串(Longest Common Substring)是一个非常经典的面试题目,在实际的程序中也有很高的实用价值。同学们不应该单单只是写出该问题的基本解决代码而已,关键还是享受把算法一步步的优化,让时间和空间复杂度一步步的减少的惊喜。
【输入形式】
两个字符串
【输出形式】
最长的公共子串,若没有则输出“no”
【样例输入】
acbcbcef
abcbced
【样例输出】
bcbce
【温馨提示】
问题的关键不在于提交代码并通过测试数据,而是你是否真正掌握了所有求解的算法。
这是一道dp题
#include <iostream>
using namespace std;
/*typedef struct stu
{
int num;
string s;
}stu;*/
//stu dp[50][50];
int main()
{ int dp;
string a , b ,temp , arr
s;
int x , y ;
cin >> a >> b ;
int len1 = a.size();
int len2 = b.size();
x = len1 - 1;
/*for( int i = 1; i <= len1 ; i++)
for( int j = 1; j <= len2 ; j++)
{
if( a[ i - 1 ] == b[ j - 1 ] )
{
dp[ i ][ j ].num = dp[ i - 1 ][ j - 1].num + 1;
dp[ i ][ j ].s = dp[ i - 1 ][ j - 1 ].s + b[ j - 1 ];
}
if( dp[ x ][ y ].num < dp [ i ][ j ].num)
{
x=i;
y=j;
}
}
if(dp[ x ][ y ].num)
cout<< dp[ x ][ y ].s ;
else
cout<<"no";*/
while(y != len2 )
{
dp = 0 ;
temp = "";
for(int i = x, j = y;i <len1 && j < len2 ; i++,j++)
{
if( a[ i ] == b[ j ] )
dp++,temp += a[ i ];
else
{
dp = 0 ; temp = "";
}
if( temp.size() > arr.size())
arr = temp;
}
if(x) x--;
else y++;
}
if( arr.size()) cout<< arr ;
else cout<<"no";
return 0;
}
5.判断两个字符串是否匹配
【问题描述】判断两个字符串是否匹配,其中一个字符串中包括通配符*或?(串)。*代表0个或多个字符,?代表一个字符
【输入形式】分两行入两个字符串,以#结束,其中一个字符串中包括通配符*或?(串),另一个为不包含*和?的确定字符串
【输出形式】判断两个字符串是否匹配,若匹配,输出yes,不匹配输出no
【样例输入】da?a*tu*e#
datastructure#
【样例输出】
yes
【样例说明】 第一个字符串中包含通配符,第二个字符串为确定字符串。字符串中可能有空格,字母均为小写字母。
【评分标准】 请尽量使用效率高的算法,如结合KMP算法的思想。提示:?可看做对任一字符的匹配,*可看做对给出的有效字符(串)的匹配
这是一道dp题
#include<bits/stdc++.h>
using namespace std;
int main(){
string a,b;
getline(cin,a);
getline(cin,b);
int m = b.length();
int n = a.length();
vector<vector<bool> > dp(m + 1, vector<bool>(n + 1, false));
dp[0][0] = 1;
for(int i = 1; i <= n; ++i) {
if(a[i - 1] == '*') dp[0][i] = 1;
else break;
}
for(int i = 1; i <= m; ++i) {
for(int j = 1; j <= n; ++j) {
if(b[i - 1] == a[j - 1] || a[j - 1] == '?') {
dp[i][j] = dp[i - 1][j - 1];
}else if(a[j - 1] == '*' && (dp[i - 1][j] || dp[i][j - 1])) {
dp[i][j] = 1;
}else{
dp[i][j] = 0;
}
}
}
if(dp[m][n]) cout << "yes" << endl;
else cout << "no" << endl;
}
6.最长回文字串
【问题描述】给定一个字符串s,找出s里第一次出现的最长的回文子串。
【样例输入1】babad
【样例输出1】bab【样例输入2】cbbd
【样例输出2】bb
可以学一下“马拉车”算法
#include <bits/stdc++.h>
#define M 100
int main()
{
char s[M]; //先设定一个字符串数组保存输入的字符串
char t[M]; //再设定一个字符串数组保存回文字符串
scanf("%s",s);
int i,j,k,l;
int j1; //j1用来保存j的值(因为在后续的程序中j需要变化,但又不能破坏j的值)
l=strlen(s);
for(j=0;j<l-1;j++)
{
j1=j; //j1算是j的替身
for(k=l-1;k>0;k--)
{
if(s[j1]!=s[k]) //判断s[j1]同s[k]
{
j1=j;
memset(t,0,sizeof(t));
continue;
}
else
{
t[0]=s[j];
t[k-j]=s[k];
j1++;
}
}
if(strlen(t)) break;
}
if(l==1||l==2&&t[0]=='\0')
{
t[0]=s[0];
}
for(i=0;i<l&&t[i]!='\0';i++)
{
printf("%c",t[i]);
}
}
7.年号字串
【问题描述】这是一道蓝桥杯的真题。小明用字母 A 对应数字 1,B 对应 2,以此类推,用 Z 对应 26。对于 27 以上的数字,小明用两位或更长位的字符串来对应,例如 AA 对应 27,AB 对 应 28,AZ 对应 52,LQ 对应 329。
请问 2019 对应的字符串是什么?请你编程解决该问题。【输入形式】数字
【输出形式】字母
【样例输入】2019
【样例输出】BYQ
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,k=0,m=26;
cin>>n;
while(n>m){
n-=m;
k++;
m*=26;
}
for(int i=0;i<=k;i++)
{ m/=26;
for(int j=0;j<26;j++)
{
if(n<=m){
cout<<char(65+j);
break;
}
else n-=m;
}
}
return 0;
}