关于一道子串问题浅思

前言:

关于一道字符串问题 想了整整一天(不断报错W( ̄_ ̄)W) 太折磨了 家人们 谁懂啊o(╥﹏╥)o


问题描述

现在有一些由英文字符组成的大小写敏感的字符串,你的任务是找到一个最长的字符串x,使得对于已经给出的字符串中的任意一个y,x或者是y的子串,或者x中的字符反序之后得到的新字符串是y的子串

输入

输入的第一行是一个整数t (1 <= t <= 10),t表示测试数据的数目。对于每一组测试数据,第一行是一个整数n (1 <= n <= 100),表示已经给出n个字符串。接下来n行,每行给出一个长度在1和100之间的字符串。

输出

对于每一组测试数据,输出一行,给出题目中要求的字符串x的长度。

样例输入 

2
3
ABCD
BCDFF
BRCD
2
rose
orchid

样例输出 

2
2


解决方案:

提示:先找出最短的字符串,然后利用最短字符串从长到短产生搜索子串及其反序子串,然后进行匹配检测,难点应该是从长到短产生搜索子串时不能有遗漏..

那么 :

取子串可用strncpy(str1,str2+i,n)内置函数(str1表示取出的子串,str2+i表示从i开始在str2中取长度为n的字符串)

反序子串可用strrev(str)函数,但是有些编译器不支持strrev函数,所以我们不妨自己写一个strrev函数

//由于有些编译器不支持strrev,所以自己写一个strrev函数
char *strrev(char *str)
{
    char *p1, *p2;
    if (! str || ! *str)
        return str;
    for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
    {

        *p1 ^= *p2;

        *p2 ^= *p1;

        *p1 ^= *p2;

    }
    return str;
}

最后上代码 一把辛酸泪O(∩_∩)O哈哈~

#include<bits/stdc++.h>
using namespace std;
int t,n;
char a[15][105];
//由于有些编译器不支持strrev,所以自己写一个strrev函数
char *strrev(char *str)
{
    char *p1, *p2;
    if (! str || ! *str)
        return str;
    for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
    {

        *p1 ^= *p2;

        *p2 ^= *p1;

        *p1 ^= *p2;

    }
    return str;
}
 

int search(char *sourcestr){
    int substrlen,found;
    int mi1=strlen(sourcestr);
	substrlen=strlen(sourcestr);
	char str1[105],str2[105];
	while(substrlen>0){
	 for(int j=0;j<=mi1-substrlen;j++){
		strncpy(str1,sourcestr+j,substrlen);
		strncpy(str2,sourcestr+j,substrlen);
		str1[substrlen]=str2[substrlen]='\0';
		
		*str2=*strrev(str2);
		//关于指针有些不太明白
		found=1;
		for(int k=1;k<=n;k++){
			if(strstr(a[k],str1)==NULL && strstr(a[k],str2)==NULL){
				found=0;
				break;
			}
		}
	    if(found==1){
	        return substrlen;
		}
	  }
	  substrlen--;
	 }
   }
int main(){
    //freopen("text.txt","r",stdin);
   cin>>t;
   while(t--){
   	cin>>n;
   	int mi=101;
   	char source[105];
   	for(int j=1;j<=n;j++){
   		cin>>a[j];
   		if(strlen(a[j])<mi){
   			mi=strlen(a[j]);
   			strcpy(source,a[j]);
		   }
	   }
	int cnt=search(source);
	cout<<cnt<<'\n';
  }
	return 0;
}

重新写了一遍,最后漏了一种情况,只有一个字符相同时的情况,调了将近两小时O(∩_∩)O哈哈~

#include<bits/stdc++.h>
using namespace std;

int main(){
 int t;
 cin>>t;
 while(t--){
 	int n;
 	cin>>n;
 	string str[105];
 	int k=0,mi=100;
 	for(int i=0;i<n;i++){
 		cin>>str[i];
 		if(str[i].length()<mi){
 			mi=str[i].length();
 			k=i;
		 }
	 }
	 int ma=0;
	 for(int i=0;i<mi;i++){
	 	for(int j=i;j<mi;j++){//for(int j=i+1;j<mi;j++)是错的,因为可能是只有一个字符相同的情况o(╥﹏╥)o
	 		char a[105];
	 		int su=0;
	 		for(int x=i;x<=j;x++)a[su++]=str[k][x];
	 		a[su]='\0';//防止数组最后乱码
	 		char b[105];
	        strcpy(b,a);
	        int len=strlen(a);
	       for(int y=0;y<len;y++){
		     b[y]=a[len-y-1];
	       }
	 		int flag=1;
	 		for(int p=0;p<n;p++){
	 			if(str[p].find(a)==-1&&str[p].find(b)==-1)flag=0;
			 }
			 if(flag==1&&j-i+1>ma)ma=j-i+1;
			 
		 }
	 }
	 cout<<ma<<'\n';
 } 
 return 0;
}

​​​​​​​


总结:

好好学习 天天代码^_^ 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值