题解 | #单词倒排#
单词倒排
http://www.nowcoder.com/practice/81544a4989df4109b33c2d65037c5836
搞点思路:
字符串中含有多种无用字符时,宜采用结束符作为标志,按字符输入。
收入的最后一个索引编号则为字符串长度-1.
但因为循环需要的i++补充了1,所以可将i之终值作为字符串长度
只有一类或者几类有用字符时,可用if筛选有用字符存入新数组。
当有按照原格式需求时(例:按照原间隔符间隔字符串),可在扫描字符串序列时候记录格式信息。 (此题由于只需要清洗其余间隔符,所以只反其道而行之记录了最后一个有用字符的索引,将所有连续间隔符都与前一个有用字符关联)(如果是需要原格式的情况,可以直接记录无用字符的索引。)
得到的间隔符数组含有重复项,因此需要再一次清洗。间隔符序列中含有相同字母索引的项全部放入新的序列,将间隔符保存的内容(字母被间隔处索引)变为新序列的索引(置位1),每次有相同索引出现均置位1,可以合多为一。
PS:因为头尾间隔符不需要,所以直接将其用一个if语句剔除。
新序列记录了字母序列索引信息,所以可以将新序列作为字母序列的信号位,对字母序列进行单个间隔符的插入,达到剔除多个间隔符的目的。
现在的序列只含有有用字符和相应断开位置含有的一个间隔符。
以下参考了一道原来做过的逆序题目,参考了一位大佬的处理程序。
因为要逆序句子而不逆序单词,可以通过格式化输出直接将这个处理后的序列按位置取出。
倒序访问序列,当访问到倒数第一个空格时候,访问空格下一个位置的地址,此时如果按照%s的格式输出,会直接输出到结束符处,实现了最后一个单词换到第一个位置输出。再输出一个空格实现分隔。然后将空格换为结束符,丢弃已经输出过的部分。再次进行循环,倒叙开始,此时访问到原倒数第二个间隔符,今最后一个间隔符,输出范围是倒数第二个间隔符到上一次循环添加的结束符位置。其余依此类推。
当到最后一个空格时,还有一个原序列的首位单词没输出,所以要记得再输出一次首位单词。
此时格式化输出可以直接写形参,默认访问第一个地址。范围到结束符结束。
#include<stdio.h>
#include<string.h>
char in,input[10000],asb[10000],forward[10000],backword[10000];
int i,j=0,k=0,flag=0,len,mark[1000],structure,ind,inde[1000],true_len;
int main()
{
while(1)
{
if(in!='\n')
{
scanf("%c",&in);//按字符输入
input[i]=in;
i++;
}
else
break;
}
len = i;
for(i=0;i<len;i++)
{
if((input[i]>='A'&&input[i]<='Z')||(input[i]>='a'&&input[i]<='z'))
{
asb[j]=input[i];//记录字母
j++;//字母之索引
}
else
{
mark[k]=j-1;//记录分隔符位置,但没解决多个分隔符问题
k++;//分隔符之索引
}
}
structure=j;//字母总数
ind=k;//间隔符总数
memset(inde,0,sizeof(int)*1000);//初始化索引数组,全置零
for(i=0;i<ind;i++)//有间隔的索引置位;去除索引重复的间隔符,只留下一个;去头尾间隔符(如果有)
{
if((mark[i]!=(-1))&&(mark[i]!=(structure-1)))//记录间隔符在字母序列之中的位置(哪个字母后)
{
inde[mark[i]]=1; //多次重复只记录一个,该位置1,将内容变为索引,头尾分隔符去除。
}
}
j=0;
for(i=0;i<structure;i++)//在字母序列的间隔处放置一空格
{
forward[j]=asb[i];
if(inde[i]==1)//通过分隔符索引位置在序列中插入空格
{
forward[j+1]=' ';
j++;
}
j++;
}
true_len=j;//字母及一间隔符长度
for(i=strlen(forward)-1;i>=0;i--)//逆序
{
if(forward[i]==' ')
{
printf("%s",&forward[i+1]);//从空格的下一位开始输出,利用printf的格式化控制,格式控制为%s时,输出到结束符为止。
forward[i]='\0';//输出后将空格写为结束符,控制下一次printf的输出范围
printf(" ");//输出空格
}
}
printf("%s",forward);//输出最后一个单词
}