回 帖 发 新 帖 刷新版面

主题:第62次编程比赛初测&最终结果

原比赛帖子地址[url]http://www.programfan.com/club/post-265093.html[/url]
初测结果如下:

                 第一组(仅含半角字符的超短数据,200*200)
diaoxue          结果错误
plane            通过(43ms)
ws0415           超时
kingofmiaomiao   结果错误,输入字符串长为1的时候
mingda           运行时错误
yxs0001          运行时错误
华山论剑         通过(11ms)
comBoy           结果错误

                 第二组(仅含半角字符的中等长度数据,10000*10000)
plane            超内存
华山论剑         超时

如果你认为你的代码需要修正者(仅限列表上的ID),请尽快在本帖子提交
否则将按照上表进行冠军评选。

以下提供一个全半混合输入函数GetStringW(类似gets)

[code=c]
//////////////////////////////////////////////////////
// IsSapce,判断是否空格换行回车制表等分隔符
//////////////////////////////////////////////////////
inline int IsSapce(int c)
{return c==EOF || c==' ' || c=='\n' || c=='\t' || c=='\r';}
//////////////////////////////////////////////////////
// GetStringW, 遇到EOF返回0,否则返回1
//////////////////////////////////////////////////////
int GetStringW(wchar_t* wcpBuffer)
{
    int c,d;
    do{
        if((d=getchar())==EOF)return 0;
    }while(IsSapce(d));
    for(;;++wcpBuffer)
    {
        c = (d?d:getchar());

        if(IsSapce(c))
        {*wcpBuffer=0; return c!=EOF;}

        if(!(c & 0x80))
        {*wcpBuffer=c; d=0; continue;}

        d = getchar();

        if(IsSapce(d))
        {*(int*)wcpBuffer=c; return d!=EOF;}

        if(d & 0x80)
        {
            *wcpBuffer=(d<<8)|c; d=0;
        }
        else
            *wcpBuffer = c;
    }
}
[/code]

使用时(需要包含头文件string.h和stdio.h或者ctring和iostream):
wchar_t a[100001],b[100001];
while (GetStringW(a) && GetStringW(b))
{
    //你的处理代码
}

//---------------------------------------------------------
最终结果请看本帖子5楼
解题报告链接:[url]http://www.programfan.com/club/post-265964.html[/url]

回复列表 (共7个回复)

沙发

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
unsigned char a[200001],b[200001];
int p[2][200001],str1[200001],str2[200001];
int main(){
  int l1,l2,i,j,sum;
  while(scanf("%s %s",a,b)!=EOF){
    for(i=0,l1=0,l2=0,j=0;a[i]&&b[j];){
      if(a[i]>127&&a[i+1]>127){
        str1[l1++]=a[i]*1000+a[i+1];
        i+=2;
      }
      else{
        str1[l1++]=a[i];
        i++;
      }
      if(b[j]>127&&b[j+1]>127){
        str2[l2++]=b[j]*1000+b[j+1];
        j+=2;
      }
      else{
        str2[l2++]=b[j];
        j++;
      }
    }
    if(a[i]){
      while(a[i]){
        if(a[i]>127&&a[i+1]>127){
        str1[l1++]=a[i]*1000+a[i+1];
        i+=2;
      }
      else{
        str1[l1++]=a[i];
        i++;
      }}
    }
    else if(b[j]){
      while(b[j]){
        if(b[j]>127&&b[j+1]>127){
        str2[l2++]=b[j]*1000+b[j+1];
        j+=2;
      }
      else{
        str2[l2++]=b[j];
        j++;
      }}
    }
    memset(p[0],0,sizeof(int)*(l2+1));
    p[1][0]=0;
    int  k=1;
    for(i=1;i<=l1;i++){
      for(j=1;j<=l2;j++){
        if(str1[i-1]==str2[j-1])
          p[k][j]=p[1-k][j-1]+1;
        else if(p[1-k][j]>=p[k][j-1])
          p[k][j]=p[1-k][j];
        else
          p[k][j]=p[k][j-1];
      }
      k=1-k;
    }
    printf("%d\n",p[1][l2]>p[0][l2]?p[1][l2]:p[0][l2]);
  }
  return 0;
}

板凳


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

//////////////////////////////////////////////////////
// IsSapce,判断是否空格换行回车制表等分隔符
//////////////////////////////////////////////////////
inline int IsSapce(int c)
{return c==EOF || c==' ' || c=='\n' || c=='\t' || c=='\r';}
//////////////////////////////////////////////////////
// GetStringW, 遇到EOF返回0,否则返回1
//////////////////////////////////////////////////////
int GetStringW(wchar_t* wcpBuffer)
{
    int c,d;
    do{
        if((d=getchar())==EOF)return 0;
    }while(IsSapce(d));
    for(;;++wcpBuffer)
    {
        c = (d?d:getchar());

        if(IsSapce(c))
        {*wcpBuffer=0; return c!=EOF;}

        if(!(c & 0x80))
        {*wcpBuffer=c; d=0; continue;}

        d = getchar();

        if(IsSapce(d))
        {*(int*)wcpBuffer=c; return d!=EOF;}

        if(d & 0x80)
        {
            *wcpBuffer=(d<<8)|c; d=0;
        }
        else
            *wcpBuffer = c;
    }
}

int MaxLen(wchar_t a[100001],wchar_t b[100001])
{
    wchar_t *pa,*pb;        //分别指向长短数组
    int la,lb;            //长短数组的长度
    int *c0;                //矩阵
    int *c1;
    int j = 0;
    int lena = 0,lenb = 0;
    bool aend = false,bend = false;
    for(int i=0;i<100001;i++)
    {
        if(!aend && a[i] != 0) lena ++;
        else aend = true;
        if(!bend && b[i] != 0) lenb ++;
        else bend = true;
        if(aend && bend)
            break;
    }
    if(lena == 0 || lenb == 0)
        return 0;
    //寻找短数组
    if(lena>lenb)
    {
        pa = a;
        pb = b;
        la = lena;
        lb = lenb;
    }
    else
    {
        pa = b;
        pb = a;
        la = lenb;
        lb = lena;
    }
    //初始化
    c0 = new int [lb + 1];
    c1 = new int [lb + 1];

    for (j=0;j<lb + 1;j++)
        c0[j] = c1[j] = 0;

    
    //计算
    //  if(x[i] = y[j]) c[i][j] = c[i-1][j-1] + 1
    //  else
    //      c[i][j] = max(c[i][j-1],c[i-1][j])
    
    for(int i=1;i<=la;i++)
    {
        for(j=1;j<=lb;j++)
        {
            if(pa[i-1] == pb[j-1])
                c1[j] = c0[j-1] + 1;
            else
                c1[j] = (c1[j-1] > c0[j] ? c1[j-1] : c0[j]);
        }
        for(j=0;j<=lb;j++)
        {
            c0[j] = c1[j];
        }
    }
    delete c0;
    delete c1;
    return c1[lb];
}

int main(void)
{

    wchar_t a[100001],b[100001];

    while (GetStringW(a) && GetStringW(b))
    {
        //你的处理代码
        cout<<MaxLen(a,b)<<endl;
    }
    
    return 0;
}

3 楼

根据飞燕提供的输入函数修改:
[code=c]
#include <stdio.h>
#include <string.h>
#include <malloc.h>

#define MAX_LEN 100001

int x[MAX_LEN], y[MAX_LEN];

int LCS(wchar_t *a, wchar_t *b)
{
    int m = wcslen(a) - 1, n = wcslen(b) - 1;
    int i, j, size = sizeof(int) * (n + 2);
    
    memset(x, 0, size);
    memset(y, 0, size);

    for (i=m; i>=0; --i)
    {
        for (j=n; j>=0; --j)
        {
            if (a[i]==b[j])
                x[j] = 1 + y[j+1];
            else
                x[j] = y[j] > x[j+1] ? y[j] : x[j+1];
        }
        memcpy(y, x, size);
    }

    return x[0];
}

int IsSapce(int c)
{
    return c==EOF || c==' ' || c=='\n' || c=='\t' || c=='\r';
}

int GetStringW(wchar_t *wcpBuffer)
{
    int c, d;
    do
    {
        if ((d=getchar())==EOF)
            return 0;
    } while(IsSapce(d));

    for (;;++wcpBuffer)
    {
        c = (d ? d : getchar());

        if (IsSapce(c))
        {
            *wcpBuffer = 0; 
            return c != EOF;
        }

        if (!(c & 0x80))
        {
            *wcpBuffer = c; d = 0; 
            continue;
        }

        d = getchar();

        if (IsSapce(d))
        {
            *(int*)wcpBuffer = c; 
            return d != EOF;
        }

        if (d & 0x80)
        {
            *wcpBuffer = (d << 8) | c;
            d = 0;
        }
        else
            *wcpBuffer = c;
    }
}

int main()
{
    wchar_t a[MAX_LEN], b[MAX_LEN];

    while (GetStringW(a) && GetStringW(b))
        printf("%d\n", LCS(a, b));

    return 0;
}
[/code]

跨越不了DP方法的O(mn),无论如何都是超时。

4 楼

测试结果:
                第一组           第二组
plane           通过(4ms)        超时
yxs0001         结果错误
华山论剑        通过(6ms)        超时

5 楼

因本题无人能够通过第二组数据,无人对经典DP法进行改进,
所以评比将不因各人的DP实现代码决定。

在当中,仅有一人自行写出接收全半混合输入代码并且积极修改算法
所以我决定plane是冠军,并且由他主持下一次比赛

本题解题报告本人会尽快发表,请留意。

6 楼

哈哈,我很幸运。正在准备中,尽快会给出下次比赛的题目

7 楼

搞不懂,是不是全角字符两个连续的ascii>127?

我来回复

您尚未登录,请登录后再回复。点此登录或注册