紫书第三章-----数组和字符串

文章内容主要参考刘汝佳著作《算法竞赛入门经典》(第2版)

memcpy用法

头文件:cstring
用法:
memcpy(b,a,sizeof(int)*k);
这是a,b都是整型数组的时候,把a数组中的前k个元素赋值给b
memcpy(b,a,sizeof(a));
把a中所有的元素赋值给b

开灯问题—注意不要输出多余的空格

参考《算法竞赛入门经典》(第2版)

题目:有n盏灯,编号为1~n,第1个人把所有灯打开,第2个人按下所有编号为2的倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关(其中关掉的灯被打开, 开着灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?输入:n和k,输出开着的灯编号。k≤n≤1000。
样例输入:
7 3
样例输出:
1 5 6 7

《算法竞赛入门经典》(第2版)39页代码参考改写如下:

#include<iostream>
#include<cstring>
using namespace std;

int main()
{
    bool a[1005];
    int n,k;
    int first=1;
    memset(a,false,sizeof(a));
    cin>>n>>k;
    for(int i=1;i<=k;i++)
        for(int j=1;j<=n;j++)
            if(j%i==0)
                a[j]=!a[j];
    for(int i=1;i<=n;i++)
    {
        if(a[i]==1)
        {
            if(first)first=0;
            else
                cout<<" ";
            cout<<i;
        }
    }
    cout<<endl;
    return 0;
}

蛇形填数

参考《算法竞赛入门经典》(第2版)

在nxn的方阵中填入1,2,…,nxn,要求填成蛇形。例如,n=4时方阵是:
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

int main()
{
    int a[20][20];
    int n;
    while(cin>>n)
    {
        memset(a,0,sizeof(a));
        int x,y;
        int tmp=a[x=0][y=n-1]=1;
        while(tmp<n*n)
        {
            while(x<n-1 && !a[x+1][y]) a[++x][y]=++tmp;
            while(y>0 && !a[x][y-1]) a[x][--y]=++tmp;
            while(x>0 && !a[x-1][y]) a[--x][y]=++tmp;
            while(y<n-1 && !a[x][y+1]) a[x][++y]=++tmp;
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(j==0)printf("%-3d",a[i][j]);
                else printf(" %-3d",a[i][j]);
            }
            cout<<endl;
        }
    }
    return 0;
}

竖式问题—补充字符串处理函数strchr、strstr、strrev、sprintf)

参考《算法竞赛入门经典》(第2版)

问题描述:
找出形如 abc*de (三位数乘以两位数) 的算式,使得在完整的竖式中,所有数字属于一个特定的数字集合。输入数字集合 (相邻数字之间没有空格),输出所有竖式。每个竖式前应有编号,之后应有一个空行。最后输出解的总数。(在样例中,为了便于观察,竖式中的空格用小数点代替,但所写的程序中应该输出空格)

样例输入:

2357

样例输出:
<1>
..775
X..33


.2325
2325.


25575

The number of solutions=1

参考代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;


int main()
{
    char s[15],buf[50];
    int kase=0;
    cin>>s;
    for(int abc=111;abc<=999;abc++)
    {
        for(int de=11;de<=99;de++)
        {
            int x=abc*(de%10),y=abc*(de/10),z=abc*de;
            sprintf(buf,"%d%d%d%d%d",abc,de,x,y,z);
            bool flag=1;
            for(int i=0;i<strlen(buf);i++)
                if(strchr(s,buf[i])==NULL) flag=0;
            if(flag)
            {
                cout<<"<"<<++kase<<">"<<endl;
                printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n",abc,de,x,y,z);
            }

        }
    }
    cout<<"The number of solutions = "<<kase<<endl;
    return 0;
}
  • 关于strchr函数:

函数原型:extern char *strchr(char *str,char character)
参数说明:str为一个字符串的指针,character为一个待查找字符。
所在库名:cstring
函数功能:从字符串str中寻找字符character第一次出现的位置。
返回说明:返回指向第一次出现字符character位置的指针,如果没找到则返回NULL。

  • 关于strstr函数

原型:char *strstr(const char *str1, const char *str2);
所在库名:cstring
找出str2字符串在str1字符串中第一次出现的位置(不包括str2的串结束符)。返回该位置的指针,如找不到,返回空指针。

  • 关于strrev函数

函数原型:extern char *strrev(char *str)
参数说明:str为源字符串,即待逆置的字符串。
所在库名:cstring
函数功能:实现字符串str的逆置。
返回说明:返回逆置字符串的指针。
代码示范:

#include<cstdio>
#include<cstring>

int main()
{
    char s[10]="abcd";
    char *p=strrev(s);
    printf("%p\n",p);
    printf("%s\n",s);
    return 0;
}

子串 OpenJ_Bailian - 2744

现在有一些由英文字符组成的大小写敏感的字符串,你的任务是找到一个最长的字符串x,使得对于已经给出的字符串中的任意一个y,x或者是y的子串,或者x中的字符反序之后得到的新字符串是y的子串。
Input
输入的第一行是一个整数t (1 <= t <= 10),t表示测试数据的数目。对于每一组测试数据,第一行是一个整数n (1 <= n <= 100),表示已经给出n个字符串。接下来n行,每行给出一个长度在1和100之间的字符串。
Output
对于每一组测试数据,输出一行,给出题目中要求的字符串x的长度。
Sample Input
2
3
ABCD
BCDFF
BRCD
2
rose
orchid
Sample Output
2
2

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int maxn=105;
int n;
char s[maxn][maxn];

void sstrrev(char s[])
{
    int len=strlen(s);
    for(int i=0;i<=(len-1)/2;i++)
        swap(s[i],s[len-1-i]);
}

bool solve(char s[maxn][maxn],char ss[])
{
    char sss[maxn];
    strcpy(sss,ss);
    sss[strlen(ss)]='\0';
    sstrrev(sss);
    sss[strlen(ss)]='\0';
    for(int i=0;i<n;i++)
        if(strstr(s[i],ss)==NULL && strstr(s[i],sss)==NULL)
            return false;
    return true;
}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int mmax=0;
        cin>>n;
        int min_len=maxn,mark;
        for(int i=0;i<n;i++)
        {
            cin>>s[i];
            if(min_len>strlen(s[i]))
            {
                min_len=strlen(s[i]);
                mark=i;
            }
        }
        for(int i=0;i<min_len;i++)
        {
            int cnt=0;
            for(int j=i;j<min_len;j++)
            {
                char s1[maxn];
                strncpy(s1,s[mark]+i,j-i+1);
                s1[j-i+1]='\0';
                if(solve(s,s1))
                {
                    cnt++;
                }
                else
                    break;
            }
            mmax=max(mmax,cnt);
        }
        cout<<mmax<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值