现在的位置: 首页 > 综合 > 正文

P1368英语课句型转换解题报告

2013年10月19日 ⁄ 综合 ⁄ 共 3072字 ⁄ 字号 评论关闭
   Name: P1368英语课句型转换
  Copyright: 始发于goal00001111的专栏;允许自由转载,但必须注明作者和出处
  Author: goal00001111
  Date: 29-12-08 15:50
  Description:      
背景 Background     
      第二节是英语课,今天作句型转换,ZLJ老师走了进来……
描述 Description     
      将陈述句转换为感叹句是英语的经典题型。因此,ZLJ老师让我们练习一下,大头的英语很差,你能帮帮他吗?
    输入:第一行,一个字符串,What或How,表示感叹句由什么来引导,第二行,一个字符串,表示原句(0<长度≤2^8)。
    输出:一行,表示改后的句子(感叹句)。
样例输入 Sample Input     
      What
    It is a lovely dog!
样例输出 Sample Output     
      What a lovely dog it is!
      
题目分析:
    这道题挂”英语课句型转换“之名,行”旋转向量”之意。
    而且出题者根本就没有考虑到英语语法的实际,原句有以'.'结尾的,有不符合语法的,有主语是数字的。
    更变态的是感叹句的谓语只有is这个单词,主语却是任意的。
    所以我们只需找到子串" is ",将其及其前面的主语(如果有的话)旋转到句末就行了。  
    如果子串" is "前面的主语不长,我们可以使用一个辅助字符串来存储它,然后使用一些简单的删除插入操作就能实现旋转了。
但是当主语很长时,使用辅助数组空间复杂度太大,甚至可能空间不够(当然此题足够),我们就要使用更高级的旋转算法
    此外要注意句子首字母移到句末后要改为小写。     
    
说明:
算法思想:删除和插入。
数据结构:字符串。
时间复杂度:O(N);
空间复杂度:方法一为O(left),left表示主语长度,方法二为O(1);
程序语言:分别用c++和pascal实现方法一,用c++实现方法二。
附注:关于向量旋转算法的详细内容请参考拙作《向量旋转算法集锦 》:
http://blog.csdn.net/goal00001111/archive/2008/12/29/3635929.aspx
 
 
方法一
c++代码:

#include<iostream>
#include<string>

using namespace std;

int main()
{
    string str1, str2;
    
    getline(cin, str1, '/n');
    getline(cin, str2, '/n');
    
    str2[str2.size()-1] = ' '; //将句尾标号'!'改为空格' '

    string temp(" is "); //只需寻找is这个单词就好了
    int r = str2.find(temp) + 3;
    
    temp = str2.substr(0, r);
    if (temp[0] >= 'A' && temp[0] <= 'Z') //首字母小写
        temp[0] += 'a' - 'A';
    
    str2 = str2.substr(r, str2.size()-r); //在str2中删除temp
    str1 += str2 + temp + '!';    //全部接到str1后面
    
    cout << str1 << endl;
    
    system("pause");
    return 0;
}

PASCAL代码:

PROGRAM P1368(INPUT, OUTPUT);
CONST
    capital = ['A'..'Z']; {大写字母}
VAR
    str1, str2, temp : ansistring;
    r : integer;
BEGIN
    readln(str1);
    readln(str2);
    
    str2[length(str2)] := ' '; {将句尾标号'!'改为空格' '}
    r := pos(' is ', str2) + 2; {只需寻找is这个单词就好了}
    
    temp := copy(str2, 1, r);
    if temp[1] in capital then {首字母小写}
        temp[1] := chr(ord(temp[1])+32);
    
    delete(str2, 1, r);
    str1 := str1 + str2 + temp + '!';
    
    writeln(str1);
END.

方法二
c++代码:

#include<iostream>
#include<string>

using namespace std;

void Swap(string & a, int left_1, int left_2, int len);
void GcdRotate(string & a, int n, int r);
char ToLow(char ch); //转换成小写字母

int main()
{
    string str1, str2;
    
    getline(cin, str1, '/n');
    getline(cin, str2, '/n');
    
    str2[0] = ToLow(str2[0]); //首字母小写
    str2[str2.size()-1] = ' '; //将句尾标号'!'改为空格' '
    
    int r = str2.find(" is ") + 3;  //只需寻找is这个单词就好了
   
    GcdRotate(str2, str2.size(), r);
    
    str1 += str2;
    str1 += '!';
    
    cout << str1 << endl;
    
    system("pause");
    return 0;
}

char ToLow(char ch) //转换成小写字母
{
    if (ch >= 'A' && ch <= 'Z')
        ch = ch - 'A' + 'a';
    return ch;
}

//交换两个长度均为len的向量块a[left_1..left_1+len) 和 a[left_2..left_2+len)
void Swap(string & a, int left_1, int left_2, int len)
{    
    char t;
    while (len > 0)
    {
        t = a[left_1];
        a[left_1] = a[left_2];
        a[left_2] = t;
        left_1++;
        left_2++;
        len--;
    }
}

//将具有n个元素的向量a向左旋转r个位置
void GcdRotate(string & a, int n, int r)
{    
    if (r == 0 || r == n) //特殊情况不用旋转
        return;
    
    int lLen, rLen, pos;    
    lLen = pos = r;
    rLen = n - r;
    while (lLen != rLen)
    {
        if (lLen > rLen) //左半段大于右半段,移动右半段
        {
            Swap(a, pos-lLen, pos, rLen);
            lLen -= rLen; //减少移动范围
        }
        else
        {
            Swap(a, pos-lLen, pos+rLen-lLen, lLen);
            rLen -= lLen;
        }
    }
    Swap(a, pos-lLen, pos, lLen); //最后交换中间段
}

抱歉!评论已关闭.