K. External memory algorithms for string problems
outofmemoryerror的5种原因及解决方案

outofmemoryerror的5种原因及解决方案[OutOfMemoryError的5种原因及解决方案]文章长度要求为3000-6000字,属于一篇相对较长的文章,请您谅解在这个自动写作平台上很难一步一步地提供如此详细和完整的答案。
然而,我将尽力为您简要介绍OutOfMemoryError的5种常见原因,并为每种原因提供一些解决方案作为参考。
1. 内存泄漏(Memory Leak)内存泄漏是指在程序运行过程中申请的内存空间没有被正确释放,导致内存不断积累而最终达到内存限制。
常见的内存泄漏情景包括未及时关闭打开的文件或数据库连接、未释放的对象引用、不合理的缓存使用等。
解决方案:- 确保在使用完内存后及时释放资源,如关闭文件或数据库连接。
- 使用弱引用(WeakReference)或软引用(SoftReference)来管理对象,以便垃圾回收器更容易回收不再需要的对象。
- 避免不必要的缓存使用,合理设置缓存的大小和过期时间。
- 使用内存分析工具(如Eclipse Memory Analyzer)检测和修复内存泄漏问题。
2. 不合理的内存分配内存不足可能是由于分配给应用程序的内存空间不足引起的。
这种情况通常发生在需要大量内存的应用程序或者在多个内存密集型应用程序共享同一台机器的情况下。
解决方案:- 增加Java虚拟机的内存限制,使用-Xmx参数调整堆内存大小。
- 优化算法和数据结构,减少内存使用量。
- 避免多个内存密集型应用程序共享同一台机器,尽量将它们部署在不同的服务器上。
3. 过大的内存对象如果程序中存在单个过大的内存对象,它可能会占用大量的堆内存空间,导致OutOfMemoryError。
解决方案:- 对于大型的数据集或者文件,考虑使用流式处理,避免一次性将所有数据加载到内存中。
- 使用分页加载或者分片处理数据,减少内存占用。
4. 递归调用过深递归调用在每次调用时都会产生新的栈帧,而栈空间是有限的,因此如果递归调用过深,就容易导致栈溢出异常,进而触发OutOfMemoryError。
最新AVR单片机相关问题

A V R单片机相关问题AVR单片机相关问题AVR读写外部RAM时出现的问题问:1,对AT90S8515来说,外部RAM的地址肯定是从0x0260开始的?2,我用ICE200仿真8515读写外部RAM,RAM大小为32K Bytes,地址映射到0x0000-0x7fff,用PC7做它的片选。
把SRE置为1,当我访问0x0300时PC7为低,这是对的,但当我不去访问0x0000-0x7fff地址空间时(例如进入死循环),问题出现了,此时PC7仍为低,按道理应为高的。
这是阿AVR与51的不同,还是我弄错了。
答:1、对AT90S8515来说,外部RAM的地址肯定是从0x0260开始的。
这是没问题的,访问0x0000-0x025F的地址为内部RAM。
2、当你访问过0x0300,PC7为低,当你不访问0x0000-0x7FFF时,由于没有一条把PC7置高的指令,所以PC7当然还为低了。
不过这也不要紧,因为当你访问0x0000-0x025F的时候,RD和WR是没有的,所以即使外部RAM被选中了,没不会产生读写。
当你访问0x0260-0x7FFF的时候,RD和WR就自动产生了。
所以就是你把外部RAM的CS直接接地也是可以的。
Mon,26 Mar 2007 15:45:57 GMT以前看到#define SREG(*(volatile unsigned char*)0x5F)这样的定义,总是感觉很奇怪,不知道为什么,今天终于有了一点点心得,请大虾们多多批砖~嵌入式系统编程,要求程序员能够利用C语言访问固定的内存地址。
既然是个地址,那么按照C语言的语法规则,这个表示地址的量应该是指针类型。
所以,知道要访问的内存地址后,比如0x5F,第一步是要把它强制转换为指针类型(unsigned char*)0x5F,AVR的SREG是八位寄存器,所以0x5F强制转换为指向unsigned char类型。
volatile(可变的)这个关键字说明这变量可能会被意想不到地改变,这样编译器就不会去假设这个变量的值了。
FREEPASCAL编译时的出错信息

FREEPASCAL编译时的出错信息Free pascal编译时的出错信息1.Out of memory[内存溢出]2.Identifier expected[缺标识符]3.Identifier not found[标识符未找到]*如:Identifier not found INTEGR[标识符INTEGER未找到] 4.Duplicate identifier[重复说明]*如:Duplicate identifier N[变量N重复说明]5.Syntax error[语法错误]*6.Error in real constant[实型常量错]7.Error in integer constant[整型常量错]8.String constant exceeds line[字符串常量跨行]9.Too many nested file[文件嵌套过多]10.Unexpected end of file[非正常文件结束]11.Line to long[行过长]12.Type Identifier expected[缺类型标识符]13.Too many open file[打开文件过多]14.Invalid file name[无效文件名]15.File not found[文件未找到]*16.Disk full[磁盘满]17.Invalid compiler directive[无效编译指示]18.Too many file[文件过多]19.Undefined type in pointer definition[指针定义中未定义类型]20.Variable identifier expected[缺变量标识符]21.Error in type definition[类型错误说明]*22.Stucture too large[结构过长]23.Set base type out of range[集合基类型越界]24.File components may not be files or object[FILE分量不能为文件或对象]25.Invalid string length[无效字符串长度]26.Type mismatch[类型不匹配]*27.Invalid subrange base type[无效子界基类型]28.Lower bound greater than upper bound[下界大于上界]29.Ordinal type expected[缺有序类型]30.Integer constant expected[缺整型常数]31.Constant expected[缺常量]32.Integer or real constant expected[缺整型或实型常量]33.Pointe type identifier expected[缺指针类型标识符]34.Invalid function result type[无效的函数结果类型]/doc/186557222.html,bel identifier expected[缺标号标识符]36.Begin expected[缺BEGIN]*37.End expected[缺END]*38.Integer expression expected[缺整型表达式]39.Ordinal expression expected[缺有序表达式]40.Boolean expression expected[缺布尔表达式]41.Operand type do not match operator[操作数与操作符不匹配]42.Error in expression[表达式错]43.Illegal expression[非法赋值]*44.Field identifier expected[缺域标识符]45.Object file too large[目标文件过大]46.Undefined external[未定义外部标识符]47.Invalid object file record[无效OBJ文件记录]48.Code segment too large[代码段过长]49.Data segment too large[数据段过长]*50.Do expected[缺DO]*51.Invalid PUBLIC definition[无效PUBLIC定义]52.Invalid EXTRN definition[无效EXTRN定义]53.Too many EXTRN definition[EXTRN定义过多]54.Of extected[缺0F]*55.INTERFACE expected[缺INTERFACE]56.Invalid relocatable reference[无效重定位引用]57.THEN expected[缺THEN]*58.TO(DOWNTO)expected[缺T0或DOWNTO]*59.Undefined forward[提前引用未定义的说明]60.Too many procedures[过程过多]61.Invalid typecast[无效类型转换]62.Division by zero[被零除]63.Invalid typecast[无效文件类型]64.Cannot Read or Write variable of this type[不能读写该类型的变量]*65.Ponter variable expected[缺指针变量]66.String variable expected[缺字符串变量]67.String expression expected[缺字符串表达式]68.Circular unit reference[单元循环引用]69.Unit name mismatchg[单元名不匹配]70.Unit version mismatch[单元版本不匹配]71.Duplicate unit name[单元重名]72.Unit file format error[单元文件格式错误]73.Implementation expected[缺IMPLEMENTATl0N]74.constant and case types do not match[常数与CASE类型不相匹配]75.Record variable expected[缺记录变量]76.Constant out of range[常量越界]77.File variable expected[缺文件变量]78.Pointer extression expected[缺指针变量]79.Integer or real expression expected[缺整型或实型表达式]/doc/186557222.html,ble not within currentblock[标号不在当前块中]/doc/186557222.html,ble already defined[标号已定义]82.Undefined lable in preceding statement part[在前面语句中标号未定义]83.Invalid@argument[无效的@参数]84.Unit expected[缺UNIT]85.“;”expected[缺“;”]*86.“:”expected[缺“:”]*87.“,”expected[缺“,”]*88.“(”expected[缺“(”)*89.“)”ex pected[缺“]”]*90.“=”expected[缺“=”]*91.“:=”expected[缺“:=”]*92.“[”or“(”expected[缺“[”或“(”)*93.“]”or“)”expected[缺“]”或“)”]*94.“..”expected[缺“.”]*95.“..”expected[缺“..”]*96.Too many variable[变量过多]97.Invalid FOR control variable[无效FOR控制变量]98.Integer variable expected[缺整型变量]99.File and procedure types are not allowed here[此处不允许用文件和过程类型] 100.Srting length mismatch[字符串长度不匹配] 101.Invalid ordering of fields[无效域顺序]102.String constant expected[缺字符串常量]103.Integer or real variable expected[缺整型或实型变量]104.Ordinal variable expected[缺顺序变量]105.INLINE error[INLINE错]106.Character expression expected[缺字符表达式]107.Too many relocation items[重定位项过多]112.Case constant out of range[CASE常量越界]113.Error in statement[语句错]114.Can’t call an interrupt procedute[不能调用中断过程]116.Must be in8087mode to complie this[必须在8087方式下编译]117.Target address not found[未找到目标地址]118.Include files are not allowed here[此处不允许包含INCLUDE文件]120.NIL expected[缺NIL]121.Invalid qualifier[无效限定符]122.Invalid variable reference[无效变量引用]123.Too many symbols[符号过多]124.Statement part too large[语句部分过长]126.Files must be var parameters[文件必须为变量参数]127.Too many conditional directive[条件符号过多]128.Misplaced conditional directive[条件指令错位]129.ENDIF directive missing[缺少ENDIF指令]130.Error in initial conditional defines[初始条件定义错]131.Header does not match previous definition[过程和函数头与前面定义的不匹配] 132.Critical disk error[严重磁盘错误] 133.Can’t evalute this expression[不能计算该表达式]*如:Can’t evalute constart expression[不能计算该常量表达式] 134.Expression incorrectly terminated[表达式错误结束]135.Invaild format specifier[无效格式说明符]136.Invalid indirect reference[无效间接引用]137.Structed variable are not allowed here[此处不允许结构变量]138.Can’t evalute without system unit[无SYSTEM单元不能计算]139.Can’t access this symbols[不能存取该符号]140.Invalid floating–point operation[无效浮点运算]141.Can’t compile overlays to memory[不能将覆盖模块编译至内存]142.Procedure or function variable expected[缺过程和函数变量]143.Invalid procedure or function reference.[无效过程或函数引用]144.Can’t overlay this unit[不能覆盖该单元]147.Object type expected[缺对象类型]148.Local object types are not allowed[不允许局部对象类型] 149.VIRTUAL expected[缺VIRTUAL]150.Method identifier expected[缺方法标识符]151.Virtual constructor are not allowed[不允许虚拟构造方法] 152.Constructor Identifier expected[缺构造函数标识符]153.Destructor Identifier expected[缺析构函数标识符]154.Fail only allowed within constructors[FAIL标准过程只允许在构造方法内使用] 155.Invalid combination of opcode and operands[无效的操作符和操作数组合] 156.Memory reference expected[缺内存引用]157.Can’t add or subtrace relocatable symbols[不能加减可重定位符号]158.Invalid register combination[无效寄存器组合]159.286/287Instructions are not enabled[未激活286/287指令]160.Invalid symbol reference[无效符号引用]161.Code generation error[代码生成错]162.ASM expected[缺ASM]。
keil c语言编程常见错误分析.

1. Warning 280:’i’:unreferenced local variable说明局部变量i 在函数中未作任何的存取操作解决方法消除函数中i 变量的宣告及即定义的参数在程序中并未调用2 Warning 206:’Music3’:missing function-prototype说明Music3( )函数未作宣告或未作外部宣告所以无法给其他函数调用解决方法将叙述void Music3(void)写在程序的最前端作宣告如果是其他文件的函数则要写成extern void Music3(void),即作外部宣告3Error:318:can’t open file ‘beep.h’说明在编译C:\8051\MANN.C 程序过程中由于main.c 用了指令#i nclude “beep.h”,但却找不到所致解决方法编写一个beep.h 的包含档并存入到c:\8051 的工作目录中4 Error 237:’LedOn’:function already has a body说明LedOn( )函数名称重复定义即有两个以上一样的函数名称解决方法修正其中的一个函数名称使得函数名称都是独立的5 ***WARNING 16:UNCALLED SEGMENT,IGNORED FOR OVERLAY PROCESSSEGMENT: ?PR?_DELAYX1MS?DELAY说明DelayX1ms( )函数未被其它函数调用也会占用程序记忆体空间解决方法去掉DelayX1ms( )函数或利用条件编译#if …..#endif,可保留该函数并不编译6 ***WARNING 6 :XDATA SPACE MEMORY OVERLAPFROM : 0025HTO: 0025H说明外部资料ROM 的0025H 重复定义地址解决方法外部资料ROM 的定义如下Pdata unsigned charXFR_ADC _at_0x25 其中XFR_ADC 变量的名称为0x25,请检查是否有其它的变量名称也是定义在0x25 处并修正它7 WARNING 206:’DelayX1ms’: missing function-prototype C:\8051\INPUT.CError 267 :’DelayX1ms ‘:requires ANSI-style prototypeC:\8051\INPUT.C说明程序中有调用DelayX1ms 函数但该函数没定义即未编写程序内容或函数已定义但未作宣告解决方法编写DelayX1ms 的内容编写完后也要作宣告或作外部宣告可在delay.h 的包含档宣告成外部以便其它函数调用8 ***WARNING 1:UNRESOLVED EXTERNAL SYMBOL SYMBOL:MUSIC3解决办法:1.是文件没有添加到工程里。
MATLAB Out of memory 问题

MATLAB "Out of memory"问题(转载)首先,我要声明,matlab自带的Help才是最权威的Matlab学习资料,如果有时间好好学习一下或是可以高效的使用的话,一定受益匪浅!比如说像Out of Memory这个问题,最开始我都是用Help memory,几乎得不到任何信息;然后就是去网上搜索此类问题的解决方法,一般有这几种:除了升级内存和升级64位系统外,下面几个方法也是解决之道。
# 增加虚拟内存%%试了,不行# 采用PACK (在命令行输入pack 整理内存空间)%%pack命令不能用在m程序中,只能用于主文件中# 采用3GB 开关启动系统(修改c盘根目录boot.ini 启动选项加上/3G 例如:multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional"/noexecute=optin /fastdetect /3G%%试了,不行# 优化程序,减少变量(使用稀疏矩阵sparse )save 保存变量load 变量,需要时再读出来# 如果必有必要,不要启动java虚拟机,采用matlab -nojvm启动(在快捷方式属性里的"..../matlab.exe")改为("...../matlab.exe" - nojvm)#关闭Matlab Server# 使用单精度single 短整数替代双精度。
%%这个管用!!!!!!Matlab 默认的数字类型是双精度浮点数(double),每个双浮点数占用8 个字节。
对于一些整数操作来说,使用双浮点数显得很浪费。
在Matlab 中可以在预先分配数组时指定使用的数字类型如以下命令:zeros(10, 10,'uint8') 。
对于浮点数,在很多精度要求不高的情况下,可以使用4个字节的单浮点数(single),可以减少一半的内存。
★Keil编译时出现错误和警告的总结

★Keil编译时出现错误和警告的总结Keil 编译时出现错误和警告的总结和C 编译器错误信息中文翻译(1)L15 重复调用***WARNING L15: MULTIPLE CALL TO SEGMENTSEGMENT: ?PR?SPI_RECEIVE_WORD?D_SPICALLER1: ?PR?VSYNC_INTERRUPT?MAINCALLER2: ?C_C51STARTUP该警告表示连接器发现有一个函数可能会被主函数和一个中断服务程序(或者调用中断服务程序的函数)同时调用,或者同时被多个中断服务程序调用。
出现这种问题的原因之一是这个函数是不可重入性函数,当该函数运行时它可能会被一个中断打断,从而使得结果发生变化并可能会引起一些变量形式的冲突(即引起函数内一些数据的丢失,可重入性函数在任何时候都可以被ISR 打断,一段时间后又可以运行,但是相应数据不会丢失)。
原因之二是用于局部变量和变量(暂且这样翻译,arguments,[自变量,变元一数值,用于确定程序或子程序的值])的内存区被其他函数的内存区所覆盖,如果该函数被中断,则它的内存区就会被使用,这将导致其他函数的内存冲突。
例如,第一个警告中函数WRITE_GMVLX1_REG 在D_GMVLX1.C 或者D_GMVLX1.A51 被定义,它被一个中断服务程序或者一个调用了中断服务程序的函数调用了,调用它的函数是VSYNC_INTERRUPT,在MAIN.C 中。
解决方法:如果你确定两个函数决不会在同一时间执行(该函数被主程序调用并且中断被禁止),并且该函数不占用内存(假设只使用寄存器),则你可以完全忽略这种警告。
如果该函数占用了内存,则应该使用连接器(linker)OVERLAY 指令将函数从覆盖分析(overlayanalysis)中除去,例如:OVERLAY (?PR?_WRITE_GMVLX1_REG?D_GMVLX1 ! *)上面的指令防止了该函数使用的内存区被其他函数覆盖。
使用MemoryAnalyzertoolMAT分析内存泄漏
使用 Memory Analyzer tool(MAT)解析内存泄漏(一)前言在平时工作过程中,有时会遇到OutOfMemoryError ,我们知道遇到Error 一般表示程序存在着严重问题,可能是灾祸性的。
所以找出是什么原因造成OutOfMemoryError特别重要。
现在向大家推荐 Eclipse Memory Analyzer tool(MAT) ,来化解我们遇到的难题。
如未说明,本文均使用Java 5.0 on Windows XP SP3环境。
为什么用 MAT从前的见解,我认为使用实时profiling/monitoring之类的工具,用一种特别实时的方式来解析哪里存在内存泄漏是很正确的。
年初使用了某profiler工具测试信息中间件中存在的内存泄漏,发现在吞吐量很高的时候 profiler 工具自己也没法响应,这让人很头痛。
今后认识到这样的工具自己就要耗资性能,且在某些条件下还发现不了泄漏。
所以,解析离线数据就特别重要了, MAT 正是这样一款工具。
为什么会内存溢出我们知道 JVM 依照 generation( 代 )来进行 GC,依照以下图所示,一共被分为 young generation( 年轻代 )、 tenured generation( 老年代 )、 permanent generation( 永久代 , perm gen) , perm gen (或称Non-Heap 非堆)是个异类,稍后会讲到。
注意,heap 空间不包括perm gen 。
绝大多数的对象都在young generation被分配,也在young generation被回收,当young generation 的空间被填满,GC会进行 minor collection( 次回收 ),此次回收不涉及到heap 中的其他 generation ,minor collection 依照 weak generational hypothesis( 弱年代假设 )来假设 young generation中大量的对象都是垃圾需要回收,minor collection的过程会非常快。
MDK调试时出现MEMORY MISMATCH错误的原因及解决方法
MDK调试时出现MEMORY MISMATCH错误的原因及解决方法一、问题在用RealView MDK + ULink仿真器进行调试时,有些情况下会提示Memory Mismatch错误。
但出现这种错误的情况并不多。
有时同一个程序,在不同时间调试可能有时候会出现这个错误,有时却没有这个错误。
似乎有一定的偶然和随机性。
二、原因看似有随机性,其实有深层的原因。
首先说明一下,MDK调试方式有两种,即在RAM中调试和在Flash中调试。
在RAM中调试时需要将可执行程序下载到RAM中,在Flash中调试时需要将可执行程序烧写到Flash中,为了方便描述暂时将前面的调试方法称为第一种调试方法,将后面的调试方法称为第二种调试方法。
在默认设置下,在开始调试时CPU会重启并会检验下载的存储空间的内容。
即采用第一种调试方法会检查RAM中的内容,采用第二种调试方法会检查Flash中的内容。
采用第一种调试方法时出现这种错误的原因有两种:其一,如果链接脚本给出了一个错误的地址空间,比如AT91SAM7S512/256/128/64/321/32/161/16的片上SRAM开始地址为0x200000,如果用户误写为0x300000,那么调试开始之时会从地址0x300000检查下载内容,而地址0x300000是没接任何存储芯片的,所以得到的是一个错误的值,会提示Memory Mismatch的错误。
其二,有些芯片的SRAM需要初始化才能正常使用,在调试时如果没有使用初始化脚本,也可能导致Memory Mismatch错误。
采用第二种调试方法时,出现这种错误的原因也有两种:其一,没有使用初始化脚本,即使Flash中内容烧写完全正确,当Flash没有完全使能时(比如有些与Falsh相关的寄存器还未配置),这时检测Flash内容会得到一个错误的结果。
其二,使用了错误的地址空间。
三、解决办法我们主要遇到这种问题首先检测地址空间是否有错,在地址空是正确的情况下,还存在这个问题的有效解决办法有两种:1、打开对话框Project->Options->Debug->ULINK Settings。
new is heap out of memory 解决方法
new is heap out of memory 解决方法(最新版3篇)篇1 目录1.概述:内存溢出的概念及原因2.解决内存溢出的方法3.具体解决 new is heap out of memory 的方法篇1正文内存溢出是指程序在运行过程中,申请的内存空间大于系统允许的最大内存空间,导致程序无法正常运行的现象。
在 Python 中,内存溢出通常发生在使用 new 操作符时,该操作符用于动态分配内存。
当 new 操作符分配的内存空间大于系统的最大内存限制时,就会出现"new is heap out of memory"的错误提示。
为了解决"new is heap out of memory"的问题,我们可以采取以下几种方法:1.优化程序代码:检查程序中是否存在内存泄漏的情况,例如未正确释放已经不再使用的对象。
内存泄漏会导致内存占用持续增加,最终引发内存溢出。
通过使用 Python 的内存分析工具,如 memory_profiler,可以找出内存泄漏的问题所在。
2.减少内存分配:在创建对象时,可以尽量使用局部变量,而非全局变量。
局部变量的生命周期仅限于函数内部,当函数结束时,这些变量会被自动释放。
此外,还可以使用生成器(generator)来节省内存,生成器允许我们在循环过程中逐步生成数据,而非一次性将所有数据存储在内存中。
3.分批处理:当需要处理大量数据时,可以将数据分成小批次进行处理。
这样可以避免一次性加载所有数据导致内存溢出。
4.使用合适的数据结构:根据实际需求选择合适的数据结构,例如使用集合(set)进行成员检查,而不是使用列表(list),可以减少内存占用。
5.升级 Python 解释器:尝试升级 Python 解释器到最新版本,以利用新版本中的性能优化和改进。
综上所述,解决"new is heap out of memory"的方法包括优化程序代码、减少内存分配、分批处理、使用合适的数据结构和升级 Python 解释器。
引发类型为“System.OutOfMemoryException”的异常
} }
var smallObject = new byte[64 * 1024];//小于85000byte的对象存在小对象堆(SOH – small object heap) Console.WriteLine(string.Format("{0}K", i * 64)); _root.Add(smallObject);//用静态List对象不断新增小对象,由于静态对象不会被回收,最终会发现物理内存和虚拟内存都耗尽,抛出OutOfMemory异常 i++; } } catch (Exception ex) { Console.WriteLine(ex); }
var largeObject = new byte[100 * 1024];//大于85000byte的对象存在一个大对象堆(LOH –large object heap) Console.WriteLine(string.Format("第{0}次:{1}K",i, i * 100)); _root.Add(largeObject);//用静态List对象不断新增对象,由于静态对象不会被回收,最终会发现虚拟内存都耗尽,抛出OutOfMemory异常!但物理内存还有4G i++; } } catch (Exception ex) { Console.WriteLine(ex); }
Console.Read(); }
} } }
示例二、物理内存还有4G,虚拟内存都被消耗完(22G),
大对象(大于85000byte)存储到大对象堆,大对象堆属于第二代堆,垃圾回收时不会压缩内存,分配一个大对象时,优先尝试在大对象堆 的尾部进行分配,如果尾部空间不足,就会尝试向操作系统请求更多的内存空间,
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
External Memory Algorithms for String Problems Kangho Roh1Maxime Crochemore2Costas S.Iliopoulos3Kunsoo Park1∗1School of Computer Science and Engineering,Seoul National University2Institut Gaspard-Monge,Universit´e de Marne-la-Vall´e e3Department of Computer Sciences,King’s College LondonAbstractIn this paper we present external memory algorithms for some string problems.Ex-ternal memory algorithms have been developed in many research areas,as the speed gapbetween fast internal memory and slow external memory continues to grow.The goalof external memory algorithms is to minimize the number of input/output operationsbetween internal memory and external memory.These years the sizes of strings such as DNA sequences are rapidly increasing.However, external memory algorithms have been developed for only a few string problems.In thispaper we considerfive string problems and present external memory algorithms for them.They are the problems offinding the maximum suffix,string matching,periodfinding,Lyndon decomposition,andfinding the minimum of a circular string.Every algorithmthat we present here runs in a linear number of I/Os in the external memory model withone disk,and they run in an optimal number of disk I/Os in the external memory modelwith multiple disks.1IntroductionData sets in many applications are often too big tofit into main memory.In such applications it is important that algorithms take into account the memory constraints of the system [30,35].In most modern systems the memory is organized into a hierarchy.At the top level,fast internal memory which is expensive and has low storage capacity is located.At the bottom level,slower external memory which is cheap and has high storage capacity is located.Therefore the input/output communication(or simply I/O)between two levels in memory hierarchy can be a bottleneck in massive data set applications.One approach to optimizing performance is to develop algorithms that minimize I/Os between internal memory and external memory.These algorithms are referred to as external memory algorithms or more simply EM algorithms.Early work in external memory algorithms focused on fundamental problems such as sort-ing,matrix multiplication,and FFT[1,29,36,3].More recently,research on EM algorithms has moved towards solving graph and geometric problems[6].Work on graph problems includes transitive closure computations,some graph traversal problems,and memory man-agement for maintaining connectivity information and paths on graphs[33,28,18].∗Corresponding Author.E-mail:kpark@theory.snu.ac.kr.This work was supported by FPR05A2-341of 21C Frontier Functional Proteomics Project from Korean Ministry of Science&Technology.String algorithmics is an important subject in algorithm research.It is used in widely varying applications such as string matching,text processing,sequence alignment,and com-pression.For instance,string matching has been one of the most extensively studied problems in computer science since it is an important task in many applications including information retrieval,library systems,DNA sequencing,signal processing,and speech/pattern recognition.These years the sizes of strings such as DNA sequences are rapidly increasing.For example, the human genome sequence is too long to be loaded in main memory.Thus external memory algorithms are necessary for string problems.However,external memory algorithms have been developed for only a few string problems:string B-trees by Ferragina and Grossi[15,16],string sorting by Arge-Ferragina-Grossi-Vitter[3],suffix trees by Farach-Ferragina-Muthukrishnan [14]and Clark and Munro[7],dictionary matching by Ferragina and Luccio[17].In this paper we present external memory algorithms for the followingfive string problems: 1)finding the maximum suffix of a string[10,11],2)string matching[5,11,19,20,25,31], 3)finding the period of a string[9,10],4)Lyndon decomposition of a string[2,13,24],5)finding the minimum of a circular string[4,23,32].These are well-studied and fundamental problems in string algorithmics.Wefirst give two external memory algorithms for the maximum suffix problem:one usesfour memory blocks and requires6 NB I/O operations,and the other uses six memory blocksand4 NB I/O operations,where N is the size of the given string and B is the block transfersize.Hence there is a tradeoffbetween memory blocks and I/O operations.Our algorithms for the remaining four problems are based on the maximum suffix algorithms;they incorporate in their algorithms either the maximum suffix algorithms directly or variations of the maximum suffix algorithms.Every algorithm we present in this paper runs in a linear number of I/Os in the external memory model with one disk.We also consider the external memory model with multiple disks.Every algorithm that we present runs in an optimal number of disk I/Os in the external memory model with multiple disks.These results with previous external memory algorithms for string problems are just the beginning of a new research area,i.e.,that of developing external memory algorithms for string problems.Many interesting problems in string algorithmics[21,22,12]can be considered for external memory algorithms.2Preliminaries2.1External memory modelWe describe a simple but reasonably accurate model of the memory system[35].In this model, there are2kinds of memory.One is internal memory and the other is external memory(disk). The internal memory and CPU are very fast,and disk access is slow.In order to amortize this access time for a larger amount of data,the disk reads or writes a large collection of contiguous data items at once.The collection of contiguous data items is called a block[35,6].In order to model the behavior of the I/O system,we can capture the main properties of the memory system as follows[35].•N=problem size(in units of data items),•M=internal memory size(in units of data items),•B=block transfer size(in units of data items),•D =number of disk drives.First we assume that D =1and there is just one CPU.We define a single I/O to be the process of reading or writing of a block (B contiguous items).The I/O complexity of an algorithm is the number of disk I/Os that the algorithm performs.We refer to O N B I/Os as “linear number of I/Os”in the external memory model with one disk.We also consider an external memory model with multiple disks.Vitter and Shriver introduced a practical parallel disk model which has D independent disk drives [36].In an I/O step,each of the D disks can transfer a block of size B simultaneously.When T (N )is the number of disk I/Os for an external memory model with one disk,T N D is the optimal number of disk I/Os in the model with multiple disks.2.2Problem definitionsIn this paper we consider five string problems.All of these problems have linear time algo-rithms in the internal memory model.We will present an efficient external memory algorithm for every problem.We assume that there is an ordering on the alphabet Σ.The notation a ≺b means that character a is lexicographically smaller than character b .The notation a b means that a =b or a ≺b .The notations ‘≺’and ‘ ’can be extended to strings in a similar way.1Maximum Suffix.The maximum suffix of a string is the lexicographically largest suffix of the string.The maximum suffix problem is to find the maximum suffix of a given string.There are several ways that this computation can be done in internal memory.One may use suffix tree construction [27],suffix array construction [26],or factor automata construction[8].Crochemore and Perrin [11]gave a simple and elegant linear-time algorithm for the maximum suffix problem.2String Matching.The string matching problem is to find all occurrences of a pattern string in a text string.There are many string matching algorithms,e.g.,Knuth-Morris-Pratt (KMP)and Boyer-Moore (BM)algorithms [25,5].In this paper we consider string matching algorithms that require only constant additional memory space [11,10,19,20,31].3Period Finding.Let T [1..N ]be a string.We call an integer p (1≤p ≤N )a period of T if T [i ]=T [i +p ]for all 1≤i ≤N −p .The shortest period of T is called the period of T and denoted by per (T ).The period finding problem is to find per (T ).There are some algorithms that find the period of a string [9,10].4Lyndon DecompositionFor a given string T ,the Lyndon decomposition is a unique decomposition T =w 1w 2···w k with the following two properties.One is that the strings w 1,w 2,···,w k are non-increasing in lexicographic order.The other is that each w i is strictly less than any of its proper circular shift.Being circular means that string A of length n has n equiva-lent representations,namely A [i..n ]A [1..i −1]for 1≤i ≤n ,where A [1..0]is the empty string.A proper circular shift A [i..n ]A [1..i −1]is a circular shift with i =1.Duval [13]gave an algorithm that finds the Lyndon decomposition of a string.5Minimum of Circular String.Let T [1..N ]be a string.The minimum-of-circular-string problem is to find the lexi-cographically smallest string among the N circular shifts of T .Shiloach [32]gave a linear-time algorithm that finds the minimum of a circular string.3Maximum Suffix 3.1MS-decompositionA string T [1..N ]has N suffixes.The maximum suffix of T is the lexicographically largest suffix among the N suffixes and is denoted by max (T ).Let v be the maximum suffix of a string T .Let u be the string such that T =uv .The string v can be written as w e w where |w |=per (v ),e ≥1,and w is a prefix of w .The sequence (u,w,e,w )is called the MS-decomposition of T ,where MS stands for maximum suffix.An MS-decomposition of T =uw e w can be expressed by four integers (i,j,k,p )such thati =|u |,j =|uw e |,k =|w |,p =|w |.(1)The 4-tuple (i,j,k,p )is called the MS-tuple of T .Example 1Let a string T be aaababab .The maximum suffix of T is babab and its period is2.So the MS-decomposition of T is (aaa,ba,2,b ),and the MS-tuple of T is (3,7,1,2)23.2Internal memory algorithmAlgorithm 1is an internal memory maximum suffix algorithm,which is a modified version of the one in [11]so that its invariants can be clearly stated.It finds max (T )of a given string T and the period of max (T ).Theorem 1gives the main idea of Algorithm 1.For any string A and a character b ,max (Ab )can be computed by Theorem 1.Theorem 1[11]Let A be a string and (i,j,k,p )be the MS-tuple of A .Let b be a character and a character b be A [i +k +1].Then we havemax (Ab )= max (A )b,if b b max (A [j +1..j +k ]b ),if b ≺b.Algorithm 1Maximum suffix algorithmfunction MAXSUFFIX (T [1..N ])i =0,j =1,k =0,p =1for j +k <N do k =k +1if T [i +k ]=T [j +k ]then if k =p then j =j +k,k =0fielse if T [i +k ] T [j +k ]then j =j +k,k =0,p =j −i else i =j,j =i +1,k =0,p =1fiod (T [i +1..N ]is the maximum suffix of T [1..N ])Algorithm 1has four integers i,j,k ,and p and has a series of iterations.After an iteration,Algorithm 1maintains the following invariant.•max (T [i +1..N ])=max (T )•(0,j −i,k,p )is the MS-tuple of T [i +1..j +k ](i.e.,T [i +1..j +k ]is the maximum suffix of itself).The initial values of i,j,k ,and p are 0,1,0,and 1,respectively.The suffix T [i +1..N ]is the maximum suffix of T when j +k becomes N .Now we describe the details of an iteration.At the beginning of an iteration,we increase k by 1and compare T [i +k ]and T [j +k ].According to the ordering between T [i +k ]and T [j +k ],three cases can occur.In each case,the variables i,j,k ,and p are computed by Theorem 1.In case 1,T [i +k ]and T [j +k ]are the same (i.e.,the periodicity continues).If k <p ,the variables i,j,k ,and p are not changed.If k =p ,the variables i,j,k ,and p become i,j +k,0,and p ,respectively.Figure 1shows case 1.i+kT[i+k]=T[j+k]T[i+k]=T[j+k] and k<pT[i+k]=T[j+k]u w w w j+kw T[i+k]=T[j+k] and k=pu w w w i+k j+ki jFigure 1:Case 1In case 2,T [i +k ]is larger than T [j +k ].By Theorem 1,T [i +1..j +k ]is the maximum suffix of T [1..j +k ]and |T [i +1..j +k ]|becomes the period of itself.Therefore the variables i,j,k ,and p become i,j +k,0and j +k −i ,respectively.Figure 2shows this situation.i+k T[i+k]>T[j+k]u j+kw Figure 2:Case 2In case 3,T [i +k ]is smaller than T [j +k ].In this case,max (T )and max (T [j +1..N ])are the same by Theorem 1.Thus,Algorithm 1finds the maximum suffix of T [j +1..N ]instead of that of T .The variables i,j,k ,and p become j,j +1,0,and 1,respectively.See Figure 3.Note that in case 1with k =p and case 2,the value of i +k decreases by k ,and the value of j +k decreases by k −1in case 3.After an iteration,the variable i +j +k increases by at least 1.Because i +j +k cannot be larger than 2N ,the time complexity of Algorithm 1is O (N )in internal memory.T[i+k]<T[j+k]uj+k i+kFigure3:Case33.3External memory algorithmFor a string T of length N,suppose that T is composed of continuous blocks in externalmemory,that is T=B1B2···BNB.Algorithm1runs in linear time in internal memory,butExample2shows that it is not an efficient algorithm in external memory.Example2Let a string A=bccd cdcd cdcd···cdcd of length N and B be4.Then Algorithm 1runs as in the following table which shows values of i,j,k,and p.Step process i j k p i+k0Initial010101case3120112case1130113case3340134case2350235case1351246case2370237case137124.. ...................After step4,i+k alternates between4and5after k increases by1at the beginning of an iteration.Therefore it accesses B1and B2alternately.So the total number of disk I/Osis about N+NB .2We present an external memory algorithm which will be called EMMS(external memory maximum suffix)algorithm.Assume that the number of disks is one.We consider an external memory model with multiple disks later.EMMS maintains four memory blocks B I,B I+K,B J, and B J+K.The initial value of each of them is thefirst block of T.While EMMS runs,B I and B J always have the blocks which are accessed by i and j,respectively.B I+K and B J+K have the blocks which are accessed by i+k and j+k,respectively,with one exception described below.We now describe the details of an iteration of EMMS.At the beginning of an iteration, variable k increases by1.If i+k accesses the next block of B I+K after the increase of k, EMMS reads the next block of B I+K to B I+K.Similarly,EMMS maintains B J+K.If case1with k=p or case2occurs,the values i+k and j become i and j+k respectively. When i+k decreases,there are three cases depending on the relation between B I and B I+K. Case X is that B I and B I+K are the same.Case Y is that B I+K is the next block of B I.Case Z is that B I+K is at least one block apart from B I.When case X or case Z occur,B I+K gets the block which is accessed by i+k.However,if case Y occurs,B I+K keeps the next block of B I(i.e.,the current block of B I+K).This is the one exception mentioned above.In case1with k<p,EMMS does nothing.In case3,i and i+k increase to j,and j and j+k become j+1.Thus,B I and B I+K get the current block of B I.For B J and B J+K,first B J gets the block accessed by j+1if it is not the current block of B J.Now the change for B J+K is the same as that of B I+K,i.e., there are three cases depending on the relation between B J and B J+K.Figure4:Case ZNow we compute the number of disk I/Os.First we compute the maximum number of disk I/Os for i and i+k.Because B I gets the block of B J when i increases,i does not need disk I/Os.So we count disk I/Os for i+k only.The variable i+k can increase from1to N−1and it can decrease on the way.If case X or case Y occurs,no disk I/O is needed until i+k becomes equal to the current value.For case Z,see Figure4.Let an integer a be i+kminus the position of the last character of B I.If case Z occurs,at most aB memory blockscan be reread until i+k becomes the current value of itself.Hence,the maximum number ofdisk I/Os for i+k is N−1B +aBfor all occurrences of case Z.Let an integerαbe the sumof all k’s of case Z,and let an integerβbe the number of case Z’s.We get N−1B +aB≤N−1B +( aB+1)≤ N−1B+aB+β≤ N−1B+kB+β≤ N−1B+ αB+β.Thevalue ofβis at most αB+1 because k is larger than B when case Z occurs.Sinceαis atmost N−1because j increases by k when i+k decreases by k and j is at most N−1,themaximum number of disk I/Os for i+k becomes2 N−1B + N−1B+1≤3 NB.Similarly,we cancompute the maximum number of disk I/Os for j and j+k.It is also bounded by3 NB .Thus,the I/O complexity of EMMS is6 NB .Now we present a modified version of EMMS which will be called mEMMS(modifiedEMMS).Its I/O complexity is4 NB .The mEMMS algorithm maintains six memory blocksB I,B I+K,B J,B J+K,B I+B,and B J+B.While mEMMS runs,B I,B I+K,B J,and B J+K al-ways have the blocks which are accessed by i,i+k,j,and j+k,respectively.The block B I+B may have the next block of B I or is null.Similarly,B J+B may have the next block of B J or is null.We now explain how mEMMS maintains B I+B.After an iteration,B I+B maintains the following invariant.If i+k accesses a block which is not B I(i.e.,i+k accesses a block to the right of B I),B I+B has the next block of B I.Otherwise,B I+B is null.The initial value of B I+B is null and that of i+k is0.While i keeps the current value, i+k can increase only by1when it increases.Thus,thefirst block which is accessed by i+k and is not B I,must be the next block of B I.B I+B gets the next block of B I when i+kD0D1D2D3D4stripe00123456789stripe110111213141516171819stripe220212223242526272829stripe330313233343536373839The data layout on the multiple disks with D=5and B=2.Figure5:Disk stripingaccesses it,and keeps it until i increases and accesses a block which is not the current block of B I.When i accesses a block which is not B I,B I+B becomes null.The invariant for B I+B is satisfied.Similarly,mEMMS maintains B J+B.We compute the number of disk I/Os.When case Z occurs,B I+B always has the nextblock of B I.Therefore in case Z,at most aB −1memory blocks are reread until i+k becomesthe current value.Thus,the maximum number of disk I/Os for i+k is N−1B +( aB−1)for all occurrences of case Z.Hence,we get N−1B +( aB−1)≤ N−1B+ aB≤N−1B +aB≤ N−1B+kB≤ N−1B+ αB≤2 NB.Similarly,the maximum numberof disk I/Os for j is also bounded by2 NB .Thus,the I/O complexity of mEMMS is4 NB.Now we consider an external memory model with multiple disks.The disk striping is a practical paradigm with multiple disks[34,35].Figure5shows an example with D=5and B=2.The input data items are striped across the disks,and I/Os are permitted only on entire stripes,one stripe at a time.For example,data items10to19can be accessed in one disk I/O time.Note that the effect of disk striping is that the multiple disks act as a single disk with a block of size DB.The disk striping paradigm can be applied to mEMMS easily.Because mEMMS maintains six memory blocks of size DB and four integers,we assume that the internal memory size Mis large enough to have them.Then,the I/O complexity becomes4 NDB .This is an optimalI/O complexity with the external disk model with multiple disks.4String MatchingMany string matching algorithmsfind the occurrences of a pattern P inside a text T by considering increasing positions in T.At each position met during the execution of an algo-rithm,a scan is done to decide whether the pattern occurs here or not,and a shift is made. Thus,these kinds of algorithms perform a series of scans and shifts,which can be referred to as scan-and-shift algorithms.For instance,the Knuth-Morris-Pratt(KMP for short)is a scan-and-shift algorithm[25].The scan of the pattern against the text at a given position can be realized in several ways.But a scan from left to right is certainly most natural.KMP maintains an array(failure function)whose size is proportional to the length of P. Whenever KMP meets a mismatch while it performs a scan,it accesses the array.Thus,if the array is too big to be stored in internal memory and mismatches occur frequently,KMP cannot be efficient in external memory.The scan-and-shift algorithm in Figure6scans T and P,and it stops when it meets a mismatch.Let a string A be P[1..x]when it meets a mismatch after x matches and b be thetext character at the position where a mismatch occurs.In this situation,the best length of a shift is per (Ab ).But the pre-computation of all periods leads to the same problem as KMP has.Hence,we will compute an approximation of per (Ab )without pre-computation.A mismatch occurs hereTEXTPATTERN PATTERNb aA Shift: per(Ab)Figure 6:Scan-and-shift algorithm4.1String matching using maximum suffixWe present an external memory string matching algorithm,which will be called the EMSM (external memory string matching)algorithm.EMSM has a series of iterations which consist of a scan and a shift just like other scan-and-shift algorithms.A shift in an iteration consists of three steps.Consider a string Ab as in Figure 6.The first step is to compute the MS-decomposition of Ab .The second step is to compute the length of the shift.In the third step,the pattern is shifted to the right.EMSM maintains the following variables and memory blocks.The variables t and r are the pointers on T and P as shown in Figure 7.Two pointers t +r and r are used when EMSM performs a scan.The block B T has the block which is accessed by t in T .Two blocks B T +R and B R basically have the block accessed by t +r and r in T and P ,respectively,with one exception described below.Moreover,a memory block B R −B is used,which has the previous block of B R or is null .The reason why EMSM maintains this block is to avoid the problem in Example 2that a variable accesses two adjacent blocks repeatedly.The way that EMSM maintains B R −B is described below.In the second step of the shift,EMSM uses two additional memory blocks.t1rpatterntext t+rFigure 7:Variables t and rNow we describe an iteration.EMSM performs a scan to the right and compares T [t +r ]and P [r ].During the scan,if r accesses the next block of B R ,B R −B gets the current block of B R and B R gets the next block of B R .The scan is stopped when |P |matches are found or a mismatch occurs.If |P |matches are found (i.e.,the pattern P occurs at the position t +1of T ),let a string V be T [t +1..t +|P |+1].If a mismatch between T [t +r ]and P [r ](i.e.,r −1matches occur),let V be T [t +1..t +r ].The string V is the same as Ab in Figure 6.After the scan,EMSM performs a shift.For thefirst step of the shift,EMSM computes the MS-decomposition of V using EMMS or mEMMS.Let uw e w and(i,j,k,p)be the MS-decomposition and the MS-tuple of V.In the second step of the shift,EMSM computes the length of the shift which is an approximation of per(V)[10].If u is a suffix of w,the length of the shift is per(X)=|w|. Otherwise,it is max(|u|,min(|w e w |,|uw e|)).The value of max(|u|,min(|w e w |,|uw e|))is not the exact value of per(V)but it is equal to or larger than a half of the length of V[10]. EMSM performs a test whether u is a suffix of w or not when|u|<|w|from the positions t+i and t+j to the left.During the test,two memory blocks,one for u and the other for w,are used.In the third step,the pattern is shifted and t increases by the length of the shift.If u is a suffix of w,EMSM doesn’t make comparisons between T[t+1..t+|V|−|w|]and P[1..|V|−|w|], which are of the form uw e−1w after the shift[10].The variables and the blocks are updated as follows.The variable r decreases to|X|−|w|+1.If u is not a suffix of w,the variable r becomes1.After the updates,if r accesses B R−B or B R after the decrease,B R keeps the current block.This is the exception for B R mentioned above.Otherwise,B R gets the block which is accessed by r and B R−B becomes null.If t+r accesses B T and B T+R is the next block of B T,B T+R keeps the current block.This is the exception for B T+R mentioned above and is similar to that for B I+B in EMMS.Now we compute the number of disk I/Os.The value t needs NB disk I/Os because itmonotonically increases.Consider the variable t+r.When u is a suffix of w in an iteration,t+r can decrease by at most |V|2 .The number of disk I/Os for t+r is linear by a similarargument that the number of disk I/Os for i+k is linear in EMMS.To reduce the number of disk I/Os,the technique for i+k in mEMMS can be used for t+r(i.e.,EMSM keeps the next block of B T using an additional block).Similarly,we can show that the number of diskI/Os for r is linear.During the second step of shift,the number of disk I/Os is at most 2|u|B .Because|u|is smaller than the length of the shift and the sum of the lengths of shifts of all iterations is smaller than N,the number of disk I/Os for the second step is linear.We can also show that the number of disk I/Os for the computation of the MS-decomposition is also linear.Hence,the I/O complexity of EMSM is linear.5Period FindingIn this section we consider the problem of computing the period of a given string.When p is a period of string T of length N,the substring T[1..N−p]is both a proper prefix and suffix of T.Therefore if EMSM meets N−i+1consecutive matches when it performs a scan at the position i,i−1is a period of T.Figure8shows it.Therefore we can modify the EMSM algorithm tofind all periods of T.The I/O complexity for periodfinding is the same as that of EMSM.6Lyndon DecompositionAny string T can be written uniquely T=w1w2···w n with the following two properties.1.the strings w1,w2,···,w n are non-increasing in lexicographic order.2.each w i(1≤i≤n)is strictly less than any of its proper circular shifts.w w w w w w w’w’i w=T[1..i−1]TFigure 8:An Overhanging Occurrence and a PeriodWe call this decomposition the Lyndon decomposition and w i the Lyndon word.Example 3shows some examples of Lyndon words and Lyndon decomposition.Example 3Consider two strings aabbc and abaab .The first string is a Lyndon word because every proper circular shift is larger than aabbc .The second string is not a Lyndon word because aabab is less than abaab .The Lyndon decomposition of T =cbbcbbbaab is c ,bbc ,b ,b ,b ,aab .2A Lyndon word has the following property.Lemma 1[13]T is a Lyndon word if and only if for each proper suffix w of T ,one has w >T .In this section we describe an external memory algorithm to find the Lyndon decom-position of a string which is called the EMLD (external memory Lyndon decomposition)algorithm.We slightly modify the EMMS algorithm to make the EMLD algorithm.We re-verse the signs in case 2and case 3of EMMS.That is,we change ‘ ’in case 2and ‘≺’in case 3to ‘≺’and ‘ ’,respectively.The EMLD algorithm outputs Lyndon words during the computation.While EMLD runs,it maintains the Lyndon decomposition of T [1..j ].The Lyndon de-composition of T [1..j ]consists of two parts.One is the Lyndon decomposition of T [1..i ]and the other is that of T [i +1..j ].EMLD maintains the following invariants.•Every Lyndon word of the Lyndon decomposition of T [1..i ]is also a Lyndon word of the Lyndon decomposition of T .That is,every Lyndon word of the Lyndon decomposition of T [1..i ]is not changed once it is determined.•The Lyndon decomposition of T [i +1..j ]has the form of T [i +1..i +p ]j −i p if T [i +1..i +p ]is a Lyndon word.The initial values of all variables are the same as those for EMMS.Case 1is the same as that of EMMS.In case 2,T [i +k ]is smaller than T [j +k ].The string T [i +1..j +k ]becomes a Lyndon word of the Lyndon decomposition of T [i +1..j +k ].。