Openjudge 字符串最大跨距

来源:互联网 发布:python入门那本书好 编辑:程序博客网 时间:2024/06/05 21:07

<好方法>

字符串最大跨距
总时间限制: 1000ms 内存限制: 65536kB

描述
有三个字符串S,S1,S2,其中,S长度不超过300,S1和S2的长度不超过10。想检测S1和S2是否同时在S中出现,且S1位于S2的左边,并在S中互不交叉(即,S1的右边界点在S2的左边界点的左侧)。计算满足上述条件的最大跨距(即,最大间隔距离:最右边的S2的起始点与最左边的S1的终止点之间的字符数目)。如果没有满足条件的S1,S2存在,则输出-1。

例如,S = “abcd123ab888efghij45ef67kl”, S1=”ab”, S2=”ef”,其中,S1在S中出现了2次,S2也在S中出现了2次,最大跨距为:18。

输入
三个串:S1, S2, S3,其间以逗号间隔(注意,S1, S2, S3中均不含逗号和空格);
输出
S1和S2在S最大跨距;若在S中没有满足条件的S1和S2,则输出-1。

样例输入
abcd123ab888efghij45ef67kl,ab,ef
样例输出
18

第一眼看到题目的时候觉得怎么这么麻烦,也搜了网上的一些题解,代码长到懒得看,于是就请教了我可爱的的远航之曲学长,的确有一个简单方法。

思路
①解决读入格式问题
由于s,s1,s2之前用逗号隔开,可以巧妙地运用cin.getline()函数,如下

    cin.getline(s,330,',');    cin.getline(s1,10,',');    cin.getline(s2,10);

②找到s中子串s1最左边的位置
很简单,直接定义指针变量pa=strstr(s,s1);

③找到s中子串s2最右边的位置
略施技巧,不要想得太复杂。由于strstr函数是从左到右查找子串,而我们想要的是最右边的子串,那可以直接把s和s2翻转,再定义指针变量pb=strstr(s,s2)就OK了,记住一定要都翻转哦。

翻转数组可以用到algorithm库里的函数reserve,格式为reverse(s+a,s+b),就是把s数组从下标a到b的左闭右开区间翻转,即[a,b)
当然数组的翻转也可以靠自定义函数来实现,如下

void revert(char t[])  {    int l=strlen(t);    for (int i=0;i<l/2;i++)    {        t[i]^=t[l-i-1];        t[l-i-1]^=t[i];        t[i]^=t[l-i-1];    }}

④由于strstr返回的是指针类型,在比较s1在s中是否位于s2左边时,我们还需稍作处理。方法就是,两个指针类型相减可得到一个整数,巧妙利用pa-s和pb-s(s表示s[0]的内存地址),再定义两个整型变量p1和p2来分别记录s1最后一个字符+1和s2第一个字符的位置,判断p1是否<=p2。

AC代码如下

//字符串最大跨距-Milky Way#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;int main(){    char s[330],a[10],b[10];    int ans=-1;    cin.getline(s,330,',');    cin.getline(a,10,',');    cin.getline(b,10);    int l=strlen(s),la=strlen(a),lb=strlen(b);     char *pa=strstr(s,a);    reverse(s,s+l);    reverse(b,b+lb);    char *pb=strstr(s,b);    if(pa!=NULL&&pb!=NULL)    {        int p1=pa-s+la;        int p2=l-(pb-s)-lb;        if(p1<=p2)ans=p2-p1;    }    printf("%d",ans);    return 0;}

复杂的问题总有好方法,我们要善于思考,不要盲目地去作答。

愿一起分享好的思路
E-mail:Milkyyyyy@yeah.net