第十五章 字符串(二)

C Primer Plus第十五章编程练习,仅供参考 第十五章编程练习 本章第一个编程练习的内容是让我们将二进制字符串转换为一个数值,传递字符串指针,逻辑并不复杂,完整程序代码以及运行结果如下: #include<stdio.h> #include<string.h> #include<math.h> int nfun(char * ptr); int main(void){ char * pbin = "01001001"; int number; number = nfun(pbin); 阅读详情

    第十五章的第二部分涉及到“短语”,其书中提出的一个问题是:给定一个文本文件作为输入,查找其中最长的重复子字符串。例如,"Ask not what your country can do for you, but what you can do for your country"中最长的重复字符串是“can do for you”,第二长的是"your country"。如何解决这个问题呢?

    文中利用两种方法来解决这个问题,第一种方法进行全文的扫描,其时间复杂度为O(n^2),这种方法将字符串作为一个整体(包括空格符)存储在一个字符数组char c[]中,因此利用的输入函数为C中的getchar(),算法比较字符串中的每个子串,并利用全局变量存储最长长度和始末数组下标。

// Program to recognize the longest duplicated string in the text

// 简易方法,时间复杂度O(n^2) 

#include <stdio.h>
#include <stdlib.h>

#define MAX 5000000

char buf[MAX];

int comlen(char *p, char *q)
{
    int count=0;
    /*
    if(*p != *q)
        return count;
    if(*p && *p == *q)
    {
          ++count;
          p++;
          q++;
    }
    */
    while(*p++ == *q++)
        ++count;
    
    return count;
}

int main()
{
    int i, j, n=0, maxlen=0, maxi, maxj, thislen;
    char c;
    //while(scanf("%s", buf) != EOF)
    //    ;
    // IN order to calculate the length n, we use getchar() instead of scanf()
    while((c=getchar()) != EOF)
        buf[n++]=c;
    //buf[n]='\0';
    
    for(i=0;i<n;i++)
    {
                    for(j=i+1;j<n;j++)  // j=i+1
                    {
                                    //if((len=comlen(i,j))>maxlen)
                                    if((thislen=comlen(&buf[i], &buf[j]))>maxlen)  // pay attention to the (a=b)>c expression
                                    {
                                                          maxlen=thislen;
                                                          maxi=i;
                                                          maxj=j;
                                    }
                    }
    }
    printf("The longest length is:%d\n",maxlen);
    printf("The longest string is: ");
    for(i=maxi;i<maxi+maxlen;i++)  // i<
        putchar(buf[i]);
  
    return 0;
}

需要注意的问题是怎样将comlen()函数中的字符指针和字符数组的下标值联系起来,其实就是用取地址符嘛!--&。


    文中的第二种方法用到了一个新颖的数据结构---后缀数组。其实在本例中就是一个字符指针数组,元素a[0]指向整个字符串,下一个元素指向从第二个字符开始的数组后缀,等等。其数组的大小为字符串的大小。而算法的思想是这样的:利用额外的空间来换取时间,首先读入输入的字符串,构建后缀数组。然后利用C库函数中的qsort()对后缀数组排序,这样排序后相邻的数据就是有最多重复字符的数据。最后比较排序后数组中的每个相邻的数据,找出最长的一个重复子串。在下面的程序中更灵活地加入了一个宏变量M,其代表的意义是这个重复子串出现的次数,也就是将解法扩展为解决“打印重复M次的最长子串”,这个问题只要在比较数组中数据时比较a[i]和a[i+M]即可。本例中对于n个字符的输入文本,后缀数组使用文本自身和额外的n个指针来表示每个子串,时间复杂度为O(nlogn)。

// Program to recognize the longest duplicated string in the text (打印最长重复子串)

// 后缀数组,时间复杂度 O(nlogn)

// Print longest string duplicated M times (打印重复M次的最长子串)
 
#include <stdio.h>
#include <stdlib.h> 
#include <string.h>

#define M 1 //
#define MAX 5000000

char buf[MAX];
char *a[MAX];  //后缀数组 

int comlen(char *p, char *q)
{
    int count=0;
    while(*p && (*p++ == *q++))
        ++count;
    
    return count;
}

int pstrcmp(char **p, char **q)  //
{
    return strcmp(*p, *q);
}

int main()
{
    int i, n=0, maxlen=0, thislen, j;
    char c;
    while((c=getchar()) != EOF)
    {
                       /*
                       buf[n]=c;
                       a[n]=&buf[n];
                       n++;
                       */
                       
                       a[n]=&buf[n];
                       buf[n++]=c;
                       
    }
    buf[n]='\0';
    
    //qsort(a, n, sizeof(char *), strcmp); //
    qsort(a, n, sizeof(char *), pstrcmp); // 指向指针的指针 
    
    /*
    for(i=0;i<n;i++)
        printf("%s\n",a[i]);
    */
    
    //for(i=0;i<(n-1);i++)   // i<n-1 不要越界 
    for(i=0;i<(n-M);i++)
    {
                    //if((thislen=comlen(a[i], a[i+1]))>maxlen)
                    if((thislen=comlen(a[i], a[i+M]))>maxlen)
                    {
                                             maxlen=thislen;
                                             j=i;
                    }
    }
    printf("The longest length is:%d\n", maxlen);
    //printf("The longest duplicated string is:%s",a[j]);
    //*精度输出字符串中的maxlen个字符 
    printf("The longest duplicated string is:%.*s\n",maxlen, a[j]);
    
    return 0;
}
需要注意的问题:1,qsort()函数中的各个参数代表的含义,其中自己重新构建的比较函数pstrcmp实际上是对strcmp库函数的一层间接调用,但是因为数组是字符指针数组,而对函数的调用需要利用到指针,所以pstrcmp()中的参数是二级指针,这在调用strcmp时需要一级的解引用*,而每个元素的大小(即函数的第三个参数为char型指针的大小)。2.在for()循环比较数组元素时需要注意下标越界的问题。3.打印输出的时候printf()函数利用“*”来精度控制字符串,指定打印字符串的长度,涉及到printf()的格式。

程序运行截图:



C Primer Plus (第六版) 第十五章_编程练习答案 no1.c //编写一个函数,把二进制字符串转换为一个数值.例如,有下面语句: //char * pbin = "01001001" ; //那么把pbin作为参数传递给函数后,他应该返回一个int类型的值25; # include <stdio.h> # include <limits.h> # include <string.h> # include ... 阅读详情

相关推荐

java笔记字符串的应用

java中equals和'=='区别以及与字符串相关的几个函数介绍

后缀数组求最长重复子串

问题描述 给定一个字符串,求出其最长重复子串 例如:abcdabcd 最长重复子串是 abcd,最长重复子串可以重叠 例如:abcdabcda,这时最长重复子串是 abcda,中间的 a 是被重叠的。 直观的解法是,首先检测长度为 n - 1 的字符串情况,如果不存在重复则检测 n - 2, 一直递减下去,直到 1 。 这种方法的时间复杂度是 O(N * N * N),其中包括三部

Hackbuteer1的专栏 2万+

恒定跨导的奥秘:基于1:3电流镜的轨到轨运放输入级设计与仿真验证

本文深入探讨了基于1:3电流镜的轨到轨运放输入级设计,重点分析了恒定跨导(GM)的实现原理与仿真验证。通过精确的电流补偿机制和工艺参数优化,解决了传统运放在电源轨附近跨导下降的问题,为模拟集成电路设计提供了可靠的低电压解决方案。

weixin_33686714的博客 516

字符串

字符串 问题:为文档中包含的单词生成一个列表 使用模板sets和strings int main(int argc, char **argv) {     set str;     set::iterator iter;     string t;     while(cin >> t)     {         str.insert(t);     }     fo

b711183612的专栏 356

RT-Thread Studio使用笔记(四):带片外Flash(W25Q128)的OTA(YModem)

前言 在学习OTA之前,请先参考上两篇博客写的关于SPI设备及W25Q128的使用方法,传送门: https://blog.youkuaiyun.com/tigerots/article/details/107423633 https://blog.youkuaiyun.com/tigerots/article/details/107933991 如何使用OTA 一. 制作BootLoader 打开Bootloader 在线获取地址,注册,并根据RT-thread官方文档生成BootLoader,官方文档已经写的很清楚,再此

tigerots的专栏 4008

WSL2+Ubuntu20.04纯root环境搭建指南:告别权限烦恼的终极方案

本文提供了一份详细的WSL2+Ubuntu20.04纯root环境搭建指南,旨在为本地开发与学习打造一个免去权限干扰、极致流畅的Linux子系统环境。通过启用WSL2、安装Ubuntu 20.04,并执行核心的root用户设置,开发者可以彻底告别频繁的sudo操作,提升在文件操作、容器调试和系统配置等方面的效率。

time3的博客 474

后缀树求最长子字符串

问题描述: 给定一个文本文件作为输入,查找其中的最长子字符串。例如, ”Ask not what your country can do for you, but what you can do for your country"中的“ can do for you"就是最长子字符串。 解题过程: 这个问题最直接的解法就是变位词程序(《编程珠玑》2.4节)。如果将输入字符串存储在c[0...

weixin_30629977的博客 167

Calibre PEX提参实战:如何用hcell和xcell文件精准屏蔽模块(附避坑指南)

本文深入解析Calibre PEX工具中hcell与xcell文件的协同工作机制,提供模块级寄生参数提取方案。通过实战案例和避坑指南,帮助工程师精准屏蔽已验证IP模块,提升仿真效率和数据一致性,适用于65nm以下工艺节点的复杂SoC设计。

weixin_29275257的博客 629

找出字符串中最长的重复子串(三种解法)

文中提出了三种:找出字符串中最长的重复子串的解法 比如 输入qweabcuwabcfw,输出结果为3 并且还能输出第二次出现abc的 a 的地址。

雪域之狼 2万+

5G NR 物理层 流程一:从帧结构到TB块,PDSCH/PUSCH 资源映射与TBS计算实战

本文详细解析了5G NR物理层流程,从帧结构到TB块的计算,重点介绍了PDSCH/PUSCH资源映射与TBS计算的实战方法。通过具体案例和公式推导,帮助工程师掌握5G NR资源分配、MCS选择及TBS量化过程,解决实际部署中的常见问题。

weixin_30897233的博客 96

我用 Claude Code 给 Spring Boot 老项目做了一次代码 Review:查出 4 类隐藏问题

接手 Spring Boot 老项目时,真正麻烦的往往不是编译报错,而是分散在业务代码中的空指针、N+1 查询、异常吞没和并发隐患。本文记录一次使用 Claude Code 辅助代码 Review 的完整流程,并给出提示词、Java 示例、修改方案和人工复核方法。

海波的专栏 400

【字符串】最长公共前缀 && 最长回文子串

​ 之前我们在动态规划笔记中提到,字符串的常见题解方法还有一个中心扩散法(至于一个马拉车算法就不讲了,学习成本高,使用率太低),它其实借助的就是回文字符串的特性,由中心自发的向外扩散寻找回文字符串,直到不符合要求!​ 另一种思路就是两两字符串进行比较,得到一个最长公共前缀之后,将其与第三个字符串比较,以此类推直到比较了所有字符串之后,得到的结果就是最长的公共前缀了!区间就是一个回文字符串,则判断是否需要更新最大长度以及回文字符串的起始位置,一直重复上述动作直到判断不符合或者越界了为止!

lirendada的博客 1545

Unity Spine 3.8 (URP) 踩坑(Shader报错修改)

提供了新思路,打算尝试一下URP。但美术使用的spine版本是3.8,项目用的Unity2021.3.11f1c2,直接导入spine URP包,shader报错:half4 不能转成 SurfaceData2D;Spine-Sprite-StandardPass-URP-2D.hlsl 也报这个错,也是同样的改法即可。今天搜索spine优化,看到一篇文章。

hrlr1230的博客 4569

【编程珠玑】第十五章 字符串(二)

给定一个文本作为输入,找出其中最长的重复字符串

Megustas_JJC的博客 516

引入 CloudWeGo 后飞书管理后台平台化改造的演进史

飞书管理后台是飞书套件专为企业管理员提供的信息管理平台,它通过引入 Kitex 泛化调用对飞书管理后台进行平台化改造,成为了企业统一数字化管理平台。本文将从三个方面为大家讲解 Kitex 泛化调用在飞书管理后台平台化改造过程中的落地实践。...

weixin_44186218的博客 1762

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

第十五章字符串

一、如何定义声明一个字符串? 1.以前的写法:数据类型 变量名=赋值; String name="张三"; 2.现在的写法:类名 对象名=new 类名(); 为什么还可以new?因为字符串本身就是一个class类,属于引用类型,使用时就必须要用new关键字创建。 String name=new String("张三");二、字符串的9个常用方法 只需要会使用即可: 1.length() 获取长度 返回int类型

m0_72658137的博客 180

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

第十五章 ObjectScript - 字符串函数

要使用数组中的单个节点,可以使用前面描述的任何函数。

yaoxin521123的博客 542

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

第十五章 字符串

字符串一、字符串使用基础二、复杂的字符串处理三、StringBuffer类的使用 一、字符串使用基础 字符串是非常常用的一种数据类型 日常中的很多信息都可以与字符串表示:密码、用户名、文章标题… 定义并初始化字符串: String str = "abc"; String str = new String();//等同于String str =""; String str = new String("abc");//等同于String str = "abc"; Stri

weixin_56258427的博客 201

第十五章 字符串

package com.tt; import java.util.Scanner; public class S4 { public static void main(String[] args) { StringBuffer sb=new StringBuffer(); int num=100; StringBuffer b1=sb.append("青春无悔");

qq_36074150的博客 1436

第十五章 字符串本地化和消息字典(一)

本文概述了字符串本地化,并描述了如何导出、导入和管理消息字典。当本地化应用程序的文本时,会创建一种语言的文本字符串清单,然后当应用程序区域设置不同时,建立约定以另一种语言替换这些消息的翻译版本。支持以下本地化字符串的过程:这种机制各不相同,但最常见的机制是 宏。代替硬编码的文字字符串,开发人员包含 宏的实例,为宏参数提供如下值: 替换为 编译代码时,编译器会在消息字典中为 宏的每个唯一实例生成条目。 消息字典是全局的,因此可以在管理门户中轻松查看(例如)。有一些类方法可以帮助完成常见任务。结果是一

yaoxin521123的博客 507

CLR via C# 第十四章—第十五章

CLR摘要

2301_79124729的博客 989

第十五章 字符串

众所周知,java提供了很多字符串截取的方式。下面就来看看大致有几种。 1.split()+正则表达式来进行截取。 将正则传入split()。返回的是一个字符串数组类型。不过通过这种方式截取会有很大的性能损耗,因为分析正则非常耗时。 String str = "abc,12,3yy98,0"; String[] strs=str.split(","); for(int i...

ansixue3661的博客 239

C Primer Plus 第十五章 课后答案

目录   复习题 1.把下面的十进制转换为二进制: a.3        b.13        c.59        d.119 2.将下面的二进制值转换为十进制、八进制和十六进制的形式: a.00010101        b.01010101        c.01001100        d.10011101 3.对下面的表达式求值,假设每个值都为8位: a.~3   ...

asdgyy的博客 4755

python教程知识(第十五章)

python知识

zzj13283671195的博客 732
上一篇: 第十五章 字符串(一)
下一篇: 第十五章 字符串(三)
ProfessionalEngineer
博客等级 码龄19年 295粉丝 154原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值