| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2050 人关注过本帖
标题:求助一道字符串处理题目
只看楼主 加入收藏
RKNO
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2018-9-7
结帖率:80%
收藏
已结贴  问题点数:20 回复次数:9 
求助一道字符串处理题目
题目如下:
给定一个长度为n的,只含0和1的字符串。可对该字符串进行如下操作:
把这个这个串截出一部分连续的前缀(长度>=0),一部分连续的后缀(长度>=0),然后将它们水平翻转后,分别连回原串的“尾部”,“首部”。

操作前:     ( a[0] ... a[i] ) a[i+1] ... a[j-1] ( a[j] ... a[n-1] )
操作后:     ( a[n-1] ... a[j] ) a[i+1] ... a[j-1] ( a[i] ... a[0] )
注意: ( 0 <= i < j < n )

然后问:此串的子序列中最长的01010101...或10101010...串的长度是多少?(如果上述操作没有得到更好的答案,可不进行)

输入格式:
一个正整数n(2<=n<=1000000),下一行是1个长度为n只含0和1的字符串。
输出格式:
求得的最长的 01...或10...串的长度。

输入样例:
4
1010
6
100110

输出样例:
4
6

样例解释:
第1个样例不需要进行操作,最长的01或10串就是4
第2个样例(10)01(10) , 把括号中的串翻转后交换得到 (01)01(01)。
tips:分清楚子串和子序列的区别。
搜索更多相关主题的帖子: 字符串 处理 长度 操作 最长 
2018-11-24 20:03
RKNO
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2018-9-7
收藏
得分:0 
这题我想了好久,感觉最难的是上限100万的测试数据。。这使很多处理都不好做。。
我发现了把前缀和后缀翻转交换这个操作,和直接把中间部分翻转一下得到的结果是一样的。不知道这个能否简化一部分操作。。
比如(10)01(10),把括号中的翻转交换,和直接翻转括号外的"01"对结果来说是等价的。
2018-11-24 20:08
复旦
Rank: 3Rank: 3
等 级:论坛游侠
威 望:2
帖 子:81
专家分:124
注 册:2018-10-29
收藏
得分:18 
下面按照我的思路写代码。代码没有编译过。你加工一下。

进行顺序重置操作的函数

主函数
int main()
{
    int n,i,j;
    char *a = (char *)malloc(4 * 1000000 * sizeof(char));  //动态方式定义
    对i,j进行适当的赋值。 (我没有完全明白你的题目的意思。不过下面函数的功能是对的。)
   
    shuffle(n,a,i,j);
    输出结果。
    return 0;
}

shuffle(int n, char a[1000000], int i, int j)  //对给定的i,j进行操作。
{
    char *tmpChar = (char *)malloc(4 * 1000000 * sizeof(char));
    int t,k=0;
    for (t=0;t<=i;t++)
        tmpChar[--n]=a[t];
    for (t=n-1;t>j;t++)
        tmpChar[k++]=a[t]
    for (t=i+1;t<=j;t++)
        tmpChar[(j-i+1)++]=a[t];
    if (strLong(n,a) < strLong(n,tmpChar))     //如果0101或者1010的最长个数比原来的字符串长度变长了,那么把a字符串赋值为顺序重置后的字符串,如果不是,什么都不做,保留a字符串。
    {
        for (t=0;t<n;t++)
            a[t]=tmpChar[t];
    }
}

求0101.。。或者1010的最长个数的函数
int strLong(int n,char a[1000000])
{
    int count=1,k=0,max=0;
    int *number = (int *)malloc(4 * 1000000 * sizeof(int));
    for (int t=0;t<1000000;t++)
        number[t]=0;
    for (i=1;i<n;i++)
    {
        if (a[i]==reverse(a[i-1]))   //下面有定义
            count++;
        else
            {
                number[k++]=count;
                count=1;
            }
    }
   
    for (int t=0;t<k;t++)
        if (number[t]>max)
            max=number[t];
    return max;
}

1,0之间翻转函数
int reverse(int i)
{
    return i==1?0:1;
}

   
2018-11-24 23:39
RKNO
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2018-9-7
收藏
得分:0 
回复 3楼 复旦
谢谢你的思路。但你的代码这复杂度肯定要超时的呀,对于每一个i和j都处理一次。
2018-11-25 10:41
复旦
Rank: 3Rank: 3
等 级:论坛游侠
威 望:2
帖 子:81
专家分:124
注 册:2018-10-29
收藏
得分:0 
我不完全明白你题目的意思。
如果只是想求最长的01010...或者101010的长度的话,
可以数0和1的个数,输出两个数的最小值。
这个很简单。
然后如果想得到
从原字符串过渡到包含最长01010...或者101010的字符串的操作内容(相关的i,j)
的话,我得好好想一想了。
2018-11-25 21:42
RKNO
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2018-9-7
收藏
得分:0 
嗯,哪里不明白,我自认为表达很明白了。
还有你说的,求最长的01010...或者101010的长度可以数0和1的个数是什么意思,这个我不是很理解?
2018-11-25 23:32
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9024
专家分:54030
注 册:2011-1-18
收藏
得分:2 
以下是引用RKNO在2018-11-25 23:32:51的发言:

还有你说的,求最长的01010...或者101010的长度可以数0和1的个数是什么意思,这个我不是很理解?
他的意思是 最终结果 = 2 * min( 字符串中0的个数,字符串中1的个数 )
比如 1001100 中有 4个0 3个1,那么最多可有3个01
比如 1001101 中有 3个0 4个1,那么最多可有3个01
2018-11-26 09:02
复旦
Rank: 3Rank: 3
等 级:论坛游侠
威 望:2
帖 子:81
专家分:124
注 册:2018-10-29
收藏
得分:0 
嗯。就是这个意思。
2018-11-26 12:02
RKNO
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2018-9-7
收藏
得分:0 
哦哦,懂了。谢谢。
2018-11-26 18:03
RKNO
Rank: 1
等 级:新手上路
帖 子:20
专家分:0
注 册:2018-9-7
收藏
得分:0 
结贴!!终于磨出来了!!这题放了好久,想不出怎么处理那个超长的字符串。但其实转换思路。并不需要模拟题目所述的操作,我们只需要知道结果就好了。
换个思路来分析:
题目要求的答案是字符串中(经过处理的或未经过处理的)最长的交替01子序列,注意是子序列,不是连续子序列,也不是子串。
也就意味着字符串中只有若干连续的0或者连续的1不起作用。
比方说:010(00)10(11)1,这个01串分别有两个0和两个1连在一起不起作用。这个时候我们尝试用题目的操作把它们拆开,试图让他们起作用。
也就是每个括号中间分开。翻转交换后得到:1(1 0)10(1 0)010 (为了方便理解我没把括号去掉),这样就多了两个字符起作用,maxlen+2。
而实际上,一次翻转交换操作最多可以使maxlen+2而已,可以理解成一次操作最多能使起作用的字符数+2。(忘了说,maxlen代表原串中最长01子序列的长度)
这样,我们只需要扫一遍原串,记录maxlen,同时记录是否有连续的0或1,就可以得出答案
上面的例子是连续的0和1都存在的情况。还有两种情况,一种是只存在连续的0,一种是只存在连续的1,分情况处理就好了。

以下附上通过代码:(不够精简请包涵)
程序代码:
#include <cstdio>
int main(void)
{
    int n;
    while (~scanf("%d\n", &n))//长度为n
    {
        char ch_last, ch_first = getchar();//字符串首位和末位,下面的判断需要
        int cnt = 1, a = ch_first-'0';
        int flag0 = 0, flag1 = 0;//记录字符串中是否有连续的0或1
        for (int i=1; i<n; ++i)
        {
            ch_last = getchar();//逐个字符输入,输入结束时ch_last保存着最后一个字符
            a ^= 1;
            if (ch_last==a+'0')
                cnt++;
            else
            {
                if (!flag0||!flag1)
                {
                    if (a==0) flag1 = 1;
                    else flag0 = 1;
                }
                a ^= 1;
            }
        }
        if (flag0&&flag1)//连续的0和连续的1
            cnt += 2;
        else if (flag0)//只有连续的0
        {
            if (ch_first-'0'||ch_last-'0')
                cnt++;
        }
        else if (flag1)//只有连续的1
        {
             if (!(ch_first-'0')||!(ch_last-'0'))
                cnt++;
        }
        printf("%d\n", cnt);
    }
    return 0;
}

2018-11-27 13:38
快速回复:求助一道字符串处理题目
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.018182 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved